• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/components/containers/unordered/include/hpx/components/containers/unordered/unordered_map.hpp
1
//  Copyright (c) 2014-2016 Hartmut Kaiser
2
//
3
//  SPDX-License-Identifier: BSL-1.0
4
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
5
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6

7
/// \file hpx/components/unordered/unordered_map.hpp
8

9
#pragma once
10

11
#include <hpx/config.hpp>
12
#include <hpx/actions_base/traits/is_distribution_policy.hpp>
13
#include <hpx/assert.hpp>
14
#include <hpx/components/client_base.hpp>
15
#include <hpx/components/get_ptr.hpp>
16
#include <hpx/components_base/component_type.hpp>
17
#include <hpx/distribution_policies/container_distribution_policy.hpp>
18
#include <hpx/modules/async_combinators.hpp>
19
#include <hpx/modules/functional.hpp>
20
#include <hpx/modules/serialization.hpp>
21
#include <hpx/modules/type_support.hpp>
22
#include <hpx/runtime_components/distributed_metadata_base.hpp>
23
#include <hpx/runtime_components/new.hpp>
24
#include <hpx/runtime_distributed/copy_component.hpp>
25

26
#include <hpx/components/containers/unordered/partition_unordered_map_component.hpp>
27
#include <hpx/components/containers/unordered/unordered_map_segmented_iterator.hpp>
28

29
#include <cstddef>
30
#include <cstdint>
31
#include <functional>
32
#include <memory>
33
#include <string>
34
#include <type_traits>
35
#include <utility>
36
#include <vector>
37

38
/// The hpx::unordered_map and its API's are defined here.
39
///
40
/// The hpx::unordered_map is a segmented data structure which is a collection
41
/// of one or more hpx::partition_unordered_maps. The hpx::unordered_map stores
42
/// the global IDs of each hpx::partition_unordered_maps.
43

44
///////////////////////////////////////////////////////////////////////////////
45
namespace hpx { namespace server {
46
    ///////////////////////////////////////////////////////////////////////////
47
    struct unordered_map_config_data
48
    {
49
        // Each partition is described by it's corresponding client object, its
×
50
        // size, and locality id.
51
        struct partition_data
52
        {
53
            partition_data()
×
54
              : locality_id_(naming::invalid_locality_id)
55
            {
56
            }
×
57

58
            partition_data(id_type const& part, std::uint32_t locality_id)
59
              : partition_(make_ready_future(part).share())
60
              , locality_id_(locality_id)
×
61
            {
×
62
            }
×
63

64
            id_type get_id() const
×
65
            {
66
                return partition_.get();
×
67
            }
68

×
69
            hpx::shared_future<id_type> partition_;
70
            std::uint32_t locality_id_;
71

72
        private:
73
            friend class hpx::serialization::access;
74

75
            template <typename Archive>
76
            void serialize(Archive& ar, unsigned)
77
            {
78
                ar & partition_ & locality_id_;
79
            }
80
        };
×
81

82
        unordered_map_config_data() {}
83

84
        unordered_map_config_data(std::vector<partition_data> const& partitions)
85
          : partitions_(partitions)
86
        {
87
        }
88

89
        unordered_map_config_data(std::vector<partition_data>&& partitions)
90
          : partitions_(HPX_MOVE(partitions))
91
        {
92
        }
93

94
        std::vector<partition_data> partitions_;
95

96
    private:
97
        friend class hpx::serialization::access;
98

99
        template <typename Archive>
100
        void serialize(Archive& ar, unsigned)
101
        {
102
            ar & partitions_;
103
        }
104
    };
×
105
}}    // namespace hpx::server
106

107
HPX_DISTRIBUTED_METADATA_DECLARATION(hpx::server::unordered_map_config_data,
108
    hpx_server_unordered_map_config_data)
109

110
///////////////////////////////////////////////////////////////////////////////
111
namespace hpx {
112
    namespace detail {
113
        ///////////////////////////////////////////////////////////////////////
114
        template <typename Key, typename T, typename Hash, typename KeyEqual>
115
        struct unordered_map_value_proxy
116
        {
117
            unordered_map_value_proxy(
118
                hpx::unordered_map<Key, T, Hash, KeyEqual>& um, Key const& key)
119
              : um_(um)
120
              , key_(key)
121
            {
122
            }
123

124
            operator T() const
125
            {
126
                return um_.get_value(launch::sync, key_);
127
            }
128

129
            template <typename T_>
130
            unordered_map_value_proxy& operator=(T_&& value)
131
            {
132
                um_.set_value(launch::sync, key_, HPX_FORWARD(T_, value));
133
                return *this;
134
            }
×
135

136
            hpx::unordered_map<Key, T, Hash, KeyEqual>& um_;
137
            Key const& key_;
138
        };
139

140
        ///////////////////////////////////////////////////////////////////////
141
        template <typename Hash, typename IsEmpty = std::is_empty<Hash>>
142
        struct unordered_hasher
143
        {
144
            unordered_hasher()
145
              : hasher_()
146
            {
×
147
            }
148

149
            explicit unordered_hasher(Hash const& hasher)
150
              : hasher_(hasher)
151
            {
152
            }
153

154
            template <typename Key>
155
            std::size_t operator()(Key const& key) const
156
            {
157
                return hasher_(key);
158
            }
159

160
            Hash hasher_;
161
        };
162

163
        template <typename Hash>
164
        struct unordered_hasher<Hash, std::true_type>
165
        {
166
            unordered_hasher() = default;
167

168
            explicit unordered_hasher(Hash const&) {}
169

170
            template <typename Key>
171
            std::size_t operator()(Key const& key) const
172
            {
173
                return Hash()(key);
174
            }
175
        };
176

177
        ///////////////////////////////////////////////////////////////////////
178
        template <typename KeyEqual, typename IsEmpty = std::is_empty<KeyEqual>>
179
        struct unordered_comparator
180
        {
181
            unordered_comparator()
182
              : equal_()
183
            {
×
184
            }
185

186
            explicit unordered_comparator(KeyEqual const& equal)
187
              : equal_(equal)
188
            {
189
            }
190

191
            template <typename Key>
192
            bool operator()(Key const& lhs, Key const& rhs) const
193
            {
194
                return equal_(lhs, rhs);
195
            }
196

197
            KeyEqual equal_;
198
        };
199

200
        template <typename KeyEqual>
201
        struct unordered_comparator<KeyEqual, std::true_type>
202
        {
203
            unordered_comparator() = default;
204

205
            explicit unordered_comparator(KeyEqual const&) {}
206

207
            template <typename Key>
208
            bool operator()(Key const& lhs, Key const& rhs) const
209
            {
210
                return KeyEqual()(lhs, rhs);
211
            }
212
        };
213

214
        ///////////////////////////////////////////////////////////////////////
215
        template <typename Hash, typename KeyEqual>
216
        struct unordered_base
217
        {
218
            unordered_base() {}
219

220
            unordered_base(Hash const& hasher, KeyEqual const& equal)
×
221
              : hasher_(hasher)
222
              , equal_(equal)
223
            {
224
            }
225

226
            unordered_hasher<Hash> hasher_;
227
            unordered_comparator<KeyEqual> equal_;
228
        };
229
    }    // namespace detail
230

231
    ///////////////////////////////////////////////////////////////////////////
232
    /// This is the unordered_map class which defines hpx::unordered_map
233
    /// functionality.
234
    ///
235
    ///  This contains the client side implementation of the hpx::unordered_map.
236
    ///  This class defines the synchronous and asynchronous API's for each of
237
    ///  the exposed functionalities.
238
    ///
239
    template <typename Key, typename T, typename Hash, typename KeyEqual>
240
    class unordered_map
241
      : hpx::components::client_base<unordered_map<Key, T, Hash, KeyEqual>,
242
            hpx::components::server::distributed_metadata_base<
243
                server::unordered_map_config_data>>
244
      , detail::unordered_base<Hash, KeyEqual>
245
    {
246
    public:
247
        typedef std::allocator<T> allocator_type;
248

249
        typedef std::size_t size_type;
250
        typedef std::ptrdiff_t difference_type;
251

252
        typedef T value_type;
253
        typedef T reference;
254
        typedef T const const_reference;
255

256
#if defined(HPX_NATIVE_MIC)
257
        typedef T* pointer;
258
        typedef T const* const_pointer;
259
#else
260
        typedef typename std::allocator_traits<allocator_type>::pointer pointer;
261
        typedef typename std::allocator_traits<allocator_type>::const_pointer
262
            const_pointer;
263
#endif
264

265
    private:
266
        typedef hpx::components::client_base<unordered_map,
267
            hpx::components::server::distributed_metadata_base<
268
                server::unordered_map_config_data>>
269
            base_type;
270
        typedef detail::unordered_base<Hash, KeyEqual> hash_base_type;
271

272
        typedef hpx::server::partition_unordered_map<Key, T, Hash, KeyEqual>
273
            partition_unordered_map_server;
274
        typedef hpx::partition_unordered_map<Key, T, Hash, KeyEqual>
275
            partition_unordered_map_client;
276

277
        struct partition_data
278
          : server::unordered_map_config_data::partition_data
279
        {
×
280
            typedef server::unordered_map_config_data::partition_data base_type;
281

282
            partition_data(id_type const& part, std::uint32_t locality_id)
283
              : base_type(part, locality_id)
284
            {
×
285
            }
×
286

287
            partition_data(base_type&& base)
288
              : base_type(HPX_MOVE(base))
289
            {
290
            }
291

292
            hpx::future<typename partition_unordered_map_server::data_type>
293
            get_data() const
294
            {
295
#if !defined(HPX_COMPUTE_DEVICE_CODE)
296
                typedef typename partition_unordered_map_server::
297
                    get_copied_data_action action_type;
298
                return hpx::async<action_type>(this->partition_.get());
299
#else
300
                HPX_ASSERT(false);
301
                return hpx::make_ready_future(
302
                    typename partition_unordered_map_server::data_type{});
303
#endif
304
            }
305

306
            hpx::future<void> set_data(
307
                typename partition_unordered_map_server::data_type&& d)
308
            {
309
#if !defined(HPX_COMPUTE_DEVICE_CODE)
310
                typedef typename partition_unordered_map_server::
311
                    set_copied_data_action action_type;
312
                return hpx::async<action_type>(
313
                    this->partition_.get(), HPX_MOVE(d));
314
#else
315
                HPX_ASSERT(false);
316
                HPX_UNUSED(d);
317
                return hpx::make_ready_future();
318
#endif
319
            }
320

321
            std::shared_ptr<partition_unordered_map_server> local_data_;
322
        };
323

324
        // The list of partitions belonging to this unordered_map.
325
        //
326
        // Each partition is described by it's corresponding client object, its
327
        // size, and locality id.
328
        typedef std::vector<partition_data> partitions_vector_type;
329

330
        // This is the vector representing the base_index and corresponding
331
        // global ID's of the underlying partitioned_vector_partitions.
332
        partitions_vector_type partitions_;
333

334
        ///////////////////////////////////////////////////////////////////////
335
        // Connect this unordered_map to the existing unordered_mapusing the
336
        // given symbolic name.
337
        void get_data_helper(id_type id, server::unordered_map_config_data data)
338
        {
339
            partitions_.clear();
340
            partitions_.reserve(data.partitions_.size());
341

342
            std::move(data.partitions_.begin(), data.partitions_.end(),
343
                std::back_inserter(partitions_));
344

345
            base_type::reset(HPX_MOVE(id));
346
        }
347

348
        // this will be called by the base class once the registered id becomes
349
        // available
350
        future<void> connect_to_helper(id_type id)
351
        {
352
            typedef typename base_type::server_component_type::get_action act;
353

354
            return async(act(), id).then(
355
                [HPX_CXX20_CAPTURE_THIS(=)](
356
                    future<server::unordered_map_config_data>&& f) -> void {
357
                    get_data_helper(id, f.get());
358
                });
359
        }
360

361
        ///////////////////////////////////////////////////////////////////////
362
        std::size_t get_partition(Key const& key) const
363
        {
364
            return this->hasher_(key) % partitions_.size();
365
        }
366

×
367
        std::vector<hpx::id_type> get_partition_ids() const
368
        {
369
            std::vector<hpx::id_type> ids;
×
370
            ids.reserve(partitions_.size());
371
            for (partition_data const& pd : partitions_)
×
372
            {
×
373
                ids.push_back(pd.get_id());
×
374
            }
375
            return ids;
×
376
        }
377

×
378
        ///////////////////////////////////////////////////////////////////////
×
379
        struct get_ptr_helper
380
        {
381
            std::size_t loc;
382
            partitions_vector_type& partitions;
383

384
            void operator()(
385
                future<std::shared_ptr<partition_unordered_map_server>>&& f)
386
                const
×
387
            {
388
                partitions[loc].local_data_ = f.get();
389
            }
390
        };
×
391

×
392
        /// \cond NOINTERNAL
393
        typedef std::pair<hpx::id_type, std::vector<hpx::id_type>>
394
            bulk_locality_result;
395
        /// \endcond
396

397
        void init(std::vector<bulk_locality_result> const& ids)
398
        {
399
            std::uint32_t this_locality = get_locality_id();
×
400
            std::vector<future<void>> ptrs;
401

×
402
            std::size_t l = 0;
×
403
            for (bulk_locality_result const& r : ids)
404
            {
405
                using naming::get_locality_id_from_id;
×
406
                std::uint32_t locality = get_locality_id_from_id(r.first);
407

408
                for (hpx::id_type const& id : r.second)
409
                {
410
                    partitions_.push_back(partition_data(id, locality));
×
411
                    if (locality == this_locality)
412
                    {
×
413
                        ptrs.push_back(
×
414
                            get_ptr<partition_unordered_map_server>(id).then(
415
                                get_ptr_helper{l, partitions_}));
×
416
                    }
417
                    ++l;
418
                }
419
            }
×
420

421
            hpx::wait_all(ptrs);
422
        }
423

424
        ///////////////////////////////////////////////////////////////////////
×
425
        // default construct partitions
426
        template <typename DistPolicy>
427
        void create(DistPolicy const& policy)
428
        {
429
            typedef partition_unordered_map_server component_type;
×
430

431
            std::size_t num_parts =
432
                traits::num_container_partitions<DistPolicy>::call(policy);
433

434
            // create as many partitions as required
435
            hpx::future<std::vector<bulk_locality_result>> f =
436
                policy.template bulk_create<false, component_type>(num_parts);
437

×
438
            // now initialize our data structures
439
            init(f.get());
440
        }
441

×
442
        // This function is called when we are creating the unordered_map. It
×
443
        // initializes the partitions based on the give parameters.
444
        template <typename DistPolicy>
445
        void create(DistPolicy const& policy, std::size_t bucket_count,
446
            Hash const& hash, KeyEqual const& equal)
447
        {
448
            typedef partition_unordered_map_server component_type;
449

450
            std::size_t num_parts =
451
                traits::num_container_partitions<DistPolicy>::call(policy);
452

453
            // create as many partitions as required
454
            hpx::future<std::vector<bulk_locality_result>> f =
455
                policy.template bulk_create<false, component_type>(
456
                    num_parts, bucket_count, hash, equal);
457

458
            // now initialize our data structures
459
            init(f.get());
460
        }
461

462
        // Perform a deep copy from the given unordered_map
463
        void copy_from(unordered_map const& rhs)
464
        {
465
            typedef
466
                typename partitions_vector_type::const_iterator const_iterator;
467

468
            std::vector<future<id_type>> objs;
469
            const_iterator end = rhs.partitions_.end();
470
            for (const_iterator it = rhs.partitions_.begin(); it != end; ++it)
471
            {
472
                typedef partition_unordered_map_server component_type;
473
                objs.push_back(hpx::components::copy<component_type>(
474
                    it->partition_.get()));
475
            }
476
            hpx::wait_all(objs);
477

478
            std::uint32_t this_locality = get_locality_id();
479
            std::vector<future<void>> ptrs;
480

481
            partitions_vector_type partitions;
482
            partitions.reserve(rhs.partitions_.size());
483
            for (std::size_t i = 0; i != rhs.partitions_.size(); ++i)
484
            {
485
                std::uint32_t locality = rhs.partitions_[i].locality_id_;
486

487
                partitions.push_back(partition_data(objs[i].get(), locality));
488

489
                if (locality == this_locality)
490
                {
491
                    ptrs.push_back(get_ptr<partition_unordered_map_server>(
492
                        partitions[i].partition_.get())
493
                            .then(get_ptr_helper{i, partitions}));
494
                }
495
            }
496

497
            hpx::wait_all(ptrs);
498

499
            std::swap(partitions_, partitions);
500
        }
501

502
    public:
503
        future<void> connect_to(std::string const& symbolic_name)
504
        {
505
            this->base_type::connect_to(symbolic_name);
506
            return this->base_type::share().then(
507
                [HPX_CXX20_CAPTURE_THIS(=)](
508
                    shared_future<id_type>&& f) -> hpx::future<void> {
509
                    return connect_to_helper(f.get());
510
                });
511
        }
512

513
        // Register this unordered_map with AGAS using the given symbolic name
514
        future<void> register_as(std::string const& symbolic_name)
515
        {
516
            std::vector<server::unordered_map_config_data::partition_data>
517
                partitions;
518
            partitions.reserve(partitions_.size());
519

520
            std::copy(partitions_.begin(), partitions_.end(),
521
                std::back_inserter(partitions));
522

523
            server::unordered_map_config_data data(HPX_MOVE(partitions));
524
            this->base_type::reset(
525
                hpx::new_<components::server::distributed_metadata_base<
526
                    server::unordered_map_config_data>>(
527
                    hpx::find_here(), HPX_MOVE(data)));
528

529
            return this->base_type::register_as(symbolic_name);
530
        }
531

532
    public:
533
        /// Default Constructor which create hpx::unordered_map with
534
        /// \a num_partitions = 1 and \a partition_size = 0. Hence overall size
535
        /// of the unordered_map is 0.
536
        unordered_map()
537
        {
538
            create(container_layout);
539
        }
540

541
        template <typename DistPolicy>
542
        unordered_map(DistPolicy const& policy,
543
            typename std::enable_if<
544
                traits::is_distribution_policy<DistPolicy>::value>::type* =
×
545
                nullptr)
546
        {
547
            create(policy);
548
        }
×
549

×
550
        explicit unordered_map(std::size_t bucket_count,
×
551
            Hash const& hash = Hash(), KeyEqual const& equal = KeyEqual())
552
          : hash_base_type(hash, equal)
553
        {
554
            create(hpx::container_layout, bucket_count, hash, equal);
555
        }
556

557
        template <typename DistPolicy>
558
        unordered_map(std::size_t bucket_count, DistPolicy const& policy,
559
            typename std::enable_if<
560
                traits::is_distribution_policy<DistPolicy>::value>::type* =
561
                nullptr)
562
        {
563
            create(policy, bucket_count, Hash(), KeyEqual());
564
        }
565

566
        template <typename DistPolicy>
567
        unordered_map(std::size_t bucket_count, Hash const& hash,
568
            DistPolicy const& policy,
569
            typename std::enable_if<
570
                traits::is_distribution_policy<DistPolicy>::value>::type* =
571
                nullptr)
572
          : hash_base_type(hash, KeyEqual())
573
        {
574
            create(policy, bucket_count, hash, KeyEqual());
575
        }
576

577
        template <typename DistPolicy>
578
        unordered_map(std::size_t bucket_count, Hash const& hash,
579
            KeyEqual const& equal, DistPolicy const& policy,
580
            typename std::enable_if<
581
                traits::is_distribution_policy<DistPolicy>::value>::type* =
582
                nullptr)
583
          : hash_base_type(hash, equal)
584
        {
585
            create(policy, bucket_count, hash, equal);
586
        }
587

588
        unordered_map(unordered_map const& rhs)
589
          : hash_base_type(rhs)
590
        {
591
            copy_from(rhs);
592
        }
593

594
        unordered_map(unordered_map&& rhs) noexcept
595
          : base_type(HPX_MOVE(static_cast<base_type&&>(rhs)))
596
          , hash_base_type(HPX_MOVE(static_cast<hash_base_type&&>(rhs)))
597
          , partitions_(HPX_MOVE(rhs.partitions_))
598
        {
599
        }
600

601
        unordered_map& operator=(unordered_map const& rhs)
602
        {
603
            if (this != &rhs)
604
                copy_from(rhs);
605
            return *this;
606
        }
607
        unordered_map& operator=(unordered_map&& rhs) noexcept
608
        {
609
            if (this != &rhs)
610
            {
611
                this->base_type::operator=(
612
                    HPX_MOVE(static_cast<base_type&&>(rhs)));
613
                this->hash_base_type::operator=(
614
                    HPX_MOVE(static_cast<hash_base_type&&>(rhs)));
615

616
                partitions_ = HPX_MOVE(rhs.partitions_);
617
            }
618
            return *this;
619
        }
620

621
        // the type every partition stores its data in
622
        typedef typename partition_unordered_map_server::data_type
623
            partition_data_type;
624

625
        std::size_t get_num_partitions() const
626
        {
627
            return partitions_.size();
628
        }
629

630
        /// \brief Array subscript operator. This does not throw any exception.
631
        ///
632
        /// \param pos Position of the element in the unordered_map
633
        ///
634
        /// \return Returns the value of the element at position represented by
635
        ///         \a pos.
636
        ///
637
        /// \note The non-const version of is operator returns a proxy object
638
        ///       instead of a real reference to the element.
639
        ///
640
        detail::unordered_map_value_proxy<Key, T, Hash, KeyEqual> operator[](
641
            Key const& pos)
642
        {
643
            return detail::unordered_map_value_proxy<Key, T, Hash, KeyEqual>(
644
                *this, pos);
645
        }
646
        T operator[](Key const& pos) const
647
        {
648
            return get_value(launch::sync, pos);
649
        }
650

651
        /// Returns the element at position \a pos in the unordered_map container.
652
        ///
653
        /// \param pos Position of the element in the unordered_map
654
        ///
655
        /// \return Returns the value of the element at position represented by
656
        ///         \a pos.
657
        ///
658
        T get_value(
659
            launch::sync_policy, Key const& pos, bool erase = false) const
660
        {
×
661
            return get_value(launch::sync, get_partition(pos), pos, erase);
662
        }
663

×
664
        /// Returns the element at position \a pos in the unordered_map container.
665
        ///
666
        /// \param part  Sequence number of the partition
667
        /// \param pos   Position of the element in the partition
668
        ///
669
        /// \return Returns the value of the element at position represented by
670
        ///         \a pos.
671
        ///
672
        T get_value(launch::sync_policy, size_type part, Key const& pos,
673
            bool erase = false) const
674
        {
×
675
            HPX_ASSERT(part < partitions_.size());
676

677
            partition_data const& part_data = partitions_[part];
678
            if (part_data.local_data_)
679
                return part_data.local_data_->get_value(pos, erase);
680

×
681
            return partition_unordered_map_client(part_data.partition_)
×
682
                .get_value(launch::sync, pos, erase);
683
        }
×
684

×
685
        /// Returns the element at position \a pos in the unordered_map container
686
        /// asynchronously.
687
        ///
688
        /// \param pos Position of the element in the unordered_map
689
        ///
690
        /// \return Returns the hpx::future to value of the element at position
691
        ///         represented by \a pos.
692
        ///
693
        future<T> get_value(Key const& pos, bool erase = false) const
694
        {
695
            return get_value(get_partition(pos), pos, erase);
696
        }
697

698
        /// Returns the element at position \a pos in the given partition in
699
        /// the unordered_map container asynchronously.
700
        ///
701
        /// \param part  Sequence number of the partition
702
        /// \param pos   Position of the element in the partition
703
        ///
704
        /// \return Returns the hpx::future to value of the element at position
705
        ///         represented by \a pos.
706
        ///
707
        future<T> get_value(
708
            size_type part, Key const& pos, bool erase = false) const
709
        {
710
            HPX_ASSERT(part < partitions_.size());
711

712
            if (partitions_[part].local_data_)
713
            {
714
                return make_ready_future(
715
                    partitions_[part].local_data_->get_value(pos, erase));
716
            }
717

718
            return partition_unordered_map_client(partitions_[part].partition_)
719
                .get_value(pos, erase);
720
        }
721

722
        /// Copy the value of \a val in the element at position \a pos in
723
        /// the unordered_map container.
724
        ///
725
        /// \param pos   Position of the element in the unordered_map
726
        /// \param val   The value to be copied
727
        ///
728
        template <typename T_>
729
        void set_value(launch::sync_policy, Key const& pos, T_&& val)
730
        {
731
            return set_value(
×
732
                launch::sync, get_partition(pos), pos, HPX_FORWARD(T_, val));
733
        }
×
734

×
735
        /// Copy the value of \a val in the element at position \a pos in
736
        /// the unordered_map container.
737
        ///
738
        /// \param part  Sequence number of the partition
739
        /// \param pos   Position of the element in the partition
740
        /// \param val   The value to be copied
741
        ///
742
        template <typename T_>
743
        void set_value(
744
            launch::sync_policy, size_type part, Key const& pos, T_&& val)
745
        {
×
746
            HPX_ASSERT(part < partitions_.size());
747

748
            partition_data const& part_data = partitions_[part];
749
            if (part_data.local_data_)
750
            {
751
                part_data.local_data_->set_value(pos, HPX_FORWARD(T_, val));
×
752
            }
753
            else
754
            {
755
                partition_unordered_map_client(part_data.partition_)
756
                    .set_value(launch::sync, pos, HPX_FORWARD(T_, val));
757
            }
×
758
        }
×
759

760
        /// Asynchronous set the element at position \a pos of the partition
×
761
        /// \a part to the given value \a val.
762
        ///
763
        /// \param pos   Position of the element in the unordered_map
764
        /// \param val   The value to be copied
765
        ///
766
        /// \return This returns the hpx::future of type void which gets ready
767
        ///         once the operation is finished.
768
        ///
769
        template <typename T_>
770
        future<void> set_value(Key const& pos, T_&& val)
771
        {
772
            return set_value(get_partition(pos), pos, HPX_FORWARD(T_, val));
773
        }
774

775
        /// Asynchronously set the element at position \a pos in
776
        /// the partition \part to the given value \a val.
777
        ///
778
        /// \param part  Sequence number of the partition
779
        /// \param pos   Position of the element in the partition
780
        /// \param val   The value to be copied
781
        ///
782
        /// \return This returns the hpx::future of type void which gets ready
783
        ///         once the operation is finished.
784
        ///
785
        template <typename T_>
786
        future<void> set_value(size_type part, Key const& pos, T_&& val)
787
        {
788
            HPX_ASSERT(part < partitions_.size());
789

790
            partition_data const& part_data = partitions_[part];
791
            if (part_data.local_data_)
792
            {
793
                part_data.local_data_->set_value(pos, HPX_FORWARD(T_, val));
794
                return make_ready_future();
795
            }
796

797
            return partition_unordered_map_client(part_data.partition_)
798
                .set_value(pos, HPX_FORWARD(T_, val));
799
        }
800

801
        /// Asynchronously compute the size of the unordered_map.
802
        ///
803
        /// \return Return the number of elements in the unordered_map
804
        ///
805
        hpx::future<std::size_t> size_async() const
806
        {
807
#if !defined(HPX_COMPUTE_DEVICE_CODE)
×
808
            std::vector<hpx::id_type> ids = get_partition_ids();
809
            if (ids.empty())
810
                return make_ready_future(std::size_t(0));
×
811

×
812
            return hpx::lcos::reduce<
×
813
                typename partition_unordered_map_server::size_action>(
814
                ids, std::plus<std::size_t>());
815
#else
816
            HPX_ASSERT(false);
×
817
            return hpx::make_ready_future(std::size_t{});
818
#endif
819
        }
820

821
        /// Compute the size compute the size of the unordered_map.
×
822
        ///
823
        /// \return Return the number of elements in the unordered_map
824
        ///
825
        std::size_t size() const
826
        {
827
            return size_async().get();
×
828
        }
829

×
830
        /// Erase all values with the given key from the partition_unordered_map
831
        /// container.
832
        ///
833
        /// \param key   Key of the element in the partition_unordered_map
834
        ///
835
        /// \return Returns the number of elements erased
836
        ///
837
        std::size_t erase(launch::sync_policy, Key const& key)
838
        {
839
            return erase(key).get();
840
        }
841

842
        std::size_t erase(launch::sync_policy, size_type part, Key const& key)
843
        {
844
            HPX_ASSERT(part < partitions_.size());
845

846
            partition_data const& part_data = partitions_[part];
847
            if (part_data.local_data_)
848
                return part_data.local_data_->erase(key);
849

850
            return partition_unordered_map_client(part_data.partition_)
851
                .erase(launch::sync, key);
852
        }
853

854
        /// Erase all values with the given key from the partition_unordered_map
855
        /// container.
856
        ///
857
        /// \param key  Key of the element in the partition_unordered_map
858
        ///
859
        /// \return This returns the hpx::future containing the number of
860
        ///         elements erased
861
        ///
862
        future<std::size_t> erase(Key const& key)
863
        {
864
            return erase(get_partition(key), key);
865
        }
866

867
        future<std::size_t> erase(size_type part, Key const& key)
868
        {
869
            HPX_ASSERT(part < partitions_.size());
870

871
            partition_data const& part_data = partitions_[part];
872
            if (part_data.local_data_)
873
                return make_ready_future(part_data.local_data_->erase(key));
874

875
            return partition_unordered_map_client(part_data.partition_)
876
                .erase(key);
877
        }
878

879
        ///////////////////////////////////////////////////////////////////////
880
        typedef segmented::segment_unordered_map_iterator<Key, T, Hash,
881
            KeyEqual, typename partitions_vector_type::iterator>
882
            segment_iterator;
883
        typedef segmented::const_segment_unordered_map_iterator<Key, T, Hash,
884
            KeyEqual, typename partitions_vector_type::const_iterator>
885
            const_segment_iterator;
886

887
        // Return global segment iterator
888
        segment_iterator segment_begin()
889
        {
890
            return segment_iterator(partitions_.begin(), this);
891
        }
892

893
        const_segment_iterator segment_begin() const
894
        {
895
            return const_segment_iterator(partitions_.cbegin(), this);
896
        }
897

898
        const_segment_iterator segment_cbegin() const    //-V524
899
        {
900
            return const_segment_iterator(partitions_.cbegin(), this);
901
        }
902

903
        segment_iterator segment_end()
904
        {
905
            return segment_iterator(partitions_.end(), this);
906
        }
907

908
        const_segment_iterator segment_end() const
909
        {
910
            return const_segment_iterator(partitions_.cend(), this);
911
        }
912

913
        const_segment_iterator segment_cend() const    //-V524
914
        {
915
            return const_segment_iterator(partitions_.cend(), this);
916
        }
917
    };
918
}    // namespace hpx
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc