From 11f7c54d4fb9576fdff39de2b4bee794fc36775f Mon Sep 17 00:00:00 2001 From: Vito G Castellana Date: Thu, 9 Dec 2021 18:48:13 -0800 Subject: [PATCH] [#204] Styleand other minor fixes inf local and distributed multimap --- include/shad/data_structures/local_multimap.h | 875 +++++++++--------- include/shad/data_structures/multimap.h | 342 ++++--- 2 files changed, 642 insertions(+), 575 deletions(-) diff --git a/include/shad/data_structures/local_multimap.h b/include/shad/data_structures/local_multimap.h index ea0f74e0..28e13c6e 100644 --- a/include/shad/data_structures/local_multimap.h +++ b/include/shad/data_structures/local_multimap.h @@ -61,9 +61,10 @@ class LocalMultimap { friend class Multimap; friend class lmultimap_iterator, - const std::pair>; - friend class lmultimap_key_iterator, const std::pair>>; + const std::pair>; + friend class lmultimap_key_iterator< + LocalMultimap, + const std::pair>>; template friend class multimap_iterator; @@ -74,15 +75,16 @@ class LocalMultimap { public: using inner_type = VTYPE; using iterator = lmultimap_iterator, - const std::pair>; - using const_iterator = lmultimap_iterator, - const std::pair>; - using key_iterator = lmultimap_key_iterator< - LocalMultimap, - const std::pair>>; - using const_key_iterator = lmultimap_key_iterator< - LocalMultimap, - const std::pair>>; + const std::pair>; + using const_iterator = + lmultimap_iterator, + const std::pair>; + using key_iterator = + lmultimap_key_iterator, + const std::pair>>; + using const_key_iterator = + lmultimap_key_iterator, + const std::pair>>; /// @brief Constructor. /// @param numInitBuckets initial number of Buckets. @@ -91,12 +93,12 @@ class LocalMultimap { buckets_array_(numInitBuckets), deleter_array_(numInitBuckets), inserter_array_(numInitBuckets), - size_(0) - { - for (uint64_t i = 0; i < numInitBuckets; i ++) { - deleter_array_[i] = 0; inserter_array_[i] = 0; - } + size_(0) { + for (uint64_t i = 0; i < numInitBuckets; i++) { + deleter_array_[i] = 0; + inserter_array_[i] = 0; } + } /// @brief Size of the multimap (number of entries). /// @return the size of the multimap. @@ -114,10 +116,11 @@ class LocalMultimap { /// @brief Asynchronously Insert a key-value pair in the multimap. /// @warning Asynchronous operations are guaranteed to have completed /// only after calling the rt::waitForCompletion(rt::Handle &handle) method. - /// @param[in,out] handle Reference to the handle to be used to wait for completion. + /// @param[in,out] handle Reference to the handle to be used to wait for + /// completion. /// @param[in] key the key. /// @param[in] value the value to copy into the multimap. - /// @return a pointer to the inserted value + /// @return a pointer to the inserted value void AsyncInsert(rt::Handle &handle, const KTYPE &key, const VTYPE &value); template @@ -130,7 +133,8 @@ class LocalMultimap { /// @brief Asynchronously remove a key and value from the multimap. /// @warning Asynchronous operations are guaranteed to have completed. /// only after calling the rt::waitForCompletion(rt::Handle &handle) method. - /// @param[in,out] handle Reference to the handle to be used to wait for completion. + /// @param[in,out] handle Reference to the handle to be used to wait for + /// completion. /// @param[in] key the key. void AsyncErase(rt::Handle &handle, const KTYPE &key); @@ -139,27 +143,28 @@ class LocalMultimap { size_ = 0; buckets_array_.clear(); buckets_array_ = std::vector(numBuckets_); - for (uint64_t i = 0; i < numBuckets_; i ++) { - deleter_array_[i] = 0; inserter_array_[i] = 0; + for (uint64_t i = 0; i < numBuckets_; i++) { + deleter_array_[i] = 0; + inserter_array_[i] = 0; } } /// @brief Result for the Lookup and AsyncLookup methods. struct LookupResult { bool found; - size_t size; /// Size of the value vector. - std::vector value; /// A copy of the value vector. + size_t size; /// Size of the value vector. + std::vector value; /// A copy of the value vector. }; /// @brief Result for the Remote Lookup method. - struct LookupRemoteResult { + struct LookupRemoteResult { bool found; - size_t size; /// Size of the value vector. - rt::Locality localLoc; /// Locality of the local site. - VTYPE * local_elems; /// Address of the value vector - /// elements at the local site - VTYPE * remote_elems; /// Address of a copy of the - /// value vector elements at the remote site + size_t size; /// Size of the value vector. + rt::Locality localLoc; /// Locality of the local site. + VTYPE *local_elems; /// Address of the value vector + /// elements at the local site + VTYPE *remote_elems; /// Address of a copy of the + /// value vector elements at the remote site }; /// @brief Asynchronously get the values associated to a key. @@ -170,22 +175,24 @@ class LocalMultimap { /// to wait for completion. /// @param[in] key The key. /// @param[out] res The result of the lookup operation. - void AsyncLookup(rt::Handle & handle, const KTYPE & key, LookupResult * result); + void AsyncLookup(rt::Handle &handle, const KTYPE &key, LookupResult *result); /// @brief Get the values associated to a key. /// @param[in] key The key. /// @param[out] res The result of the lookup operation. - bool Lookup(const KTYPE & key, LookupResult * result); + bool Lookup(const KTYPE &key, LookupResult *result); /// @brief Make a local copy of the values associated to a key and /// return the size and address of the local copy. /// /// @param[in] key The key. /// @param[out] local_result The result of the lookup operation. - void LookupFromRemote(KTYPE & key, LookupRemoteResult * remote_result); + void LookupFromRemote(KTYPE &key, LookupRemoteResult *remote_result); - /// @brief Apply a user-defined function to every element of an entry's value array. - /// @tparam ApplyFunT User-defined function type. The function prototype should be: + /// @brief Apply a user-defined function to every element of an entry's value + /// array. + /// @tparam ApplyFunT User-defined function type. The function prototype + /// should be: /// @code /// void(const KTYPE&, VTYPE&, Args&); /// @endcode @@ -195,14 +202,15 @@ class LocalMultimap { /// @param function The function to apply. /// @param args The function arguments. template - void Apply(const KTYPE &key, ApplyFunT &&function, Args &... args) { + void Apply(const KTYPE &key, ApplyFunT &&function, Args &...args) { LookupResult result; - Lookup(key, & result); + Lookup(key, &result); for (auto x : result.value) function(key, x, args...); } /// @brief Asynchronously apply a user-defined function to a key-value pair. - /// @tparam ApplyFunT User-defined function type. The function prototype should be: + /// @tparam ApplyFunT User-defined function type. The function prototype + /// should be: /// @code /// void(rt::Handle &handle, const KTYPE&, VTYPE&, Args&); /// @endcode @@ -213,10 +221,12 @@ class LocalMultimap { /// @param function The function to apply. /// @param args The function arguments. template - void AsyncApply(rt::Handle &handle, const KTYPE &key, ApplyFunT &&function, Args &... args); + void AsyncApply(rt::Handle &handle, const KTYPE &key, ApplyFunT &&function, + Args &...args); /// @brief Apply a user-defined function to each key-value pair. - /// @tparam ApplyFunT User-defined function type. The function prototype should be: + /// @tparam ApplyFunT User-defined function type. The function prototype + /// should be: /// @code /// void(const KTYPE&, VTYPE&, Args&); /// @endcode @@ -225,11 +235,12 @@ class LocalMultimap { /// @param function The function to apply. /// @param args The function arguments. template - void ForEachEntry(ApplyFunT &&function, Args &... args); + void ForEachEntry(ApplyFunT &&function, Args &...args); - /// @brief Asynchronously apply a user-defined function to each key-value pair. + /// @brief Asynchronously apply a user-defined function to each key-value + /// pair. /// - /// @tparam ApplyFunT User-defined function type. The function prototype + /// @tparam ApplyFunT User-defined function type. The function prototype /// should be: /// @code /// void(shad::rt::Handle&, const KTYPE&, VTYPE&, Args&); @@ -239,11 +250,13 @@ class LocalMultimap { /// @warning Asynchronous operations are guaranteed to have completed only /// after calling the rt::waitForCompletion(rt::Handle &handle) method. /// - /// @param[in,out] handle Reference to the handle to be used to wait for completion. + /// @param[in,out] handle Reference to the handle to be used to wait for + /// completion. /// @param function The function to apply. /// @param args The function arguments. template - void AsyncForEachEntry(rt::Handle &handle, ApplyFunT &&function, Args &... args); + void AsyncForEachEntry(rt::Handle &handle, ApplyFunT &&function, + Args &...args); /// @brief Apply a user-defined function to each key. /// @tparam ApplyFunT User-defined function type. @@ -255,7 +268,7 @@ class LocalMultimap { /// @param function The function to apply. /// @param args The function arguments. template - void ForEachKey(ApplyFunT &&function, Args &... args); + void ForEachKey(ApplyFunT &&function, Args &...args); /// @brief Asynchronously apply a user-defined function to each key. /// @tparam ApplyFunT User-defined function type. @@ -266,29 +279,34 @@ class LocalMultimap { /// @tparam ...Args Types of the function arguments. /// @warning Asynchronous operations are guaranteed to have completed. /// only after calling the rt::waitForCompletion(rt::Handle &handle) method. - /// @param[in,out] handle Reference to the handle to be used to wait for completion. + /// @param[in,out] handle Reference to the handle to be used to wait for + /// completion. /// @param function The function to apply. /// @param args The function arguments. template - void AsyncForEachKey(rt::Handle &handle, ApplyFunT &&function, Args &... args); + void AsyncForEachKey(rt::Handle &handle, ApplyFunT &&function, Args &...args); /// @brief Print all the entries in the multimap. - /// @warning std::ostream & operator<< must be defined for both KTYPE and VTYPE + /// @warning std::ostream & operator<< must be defined for both KTYPE and + /// VTYPE void PrintAllEntries(); /// @brief Print all the keys in the multimap. - /// @warning std::ostream & operator<< must be defined for both KTYPE and VTYPE + /// @warning std::ostream & operator<< must be defined for both KTYPE and + /// VTYPE void PrintAllKeys(); iterator begin() { Entry *firstEntry = &buckets_array_[0].getEntry(0); if (firstEntry->state == USED) { - iterator cbeg(this, 0, 0, &buckets_array_[0], firstEntry, firstEntry->value.begin()); + iterator cbeg(this, 0, 0, &buckets_array_[0], firstEntry, + firstEntry->value.begin()); return cbeg; } - iterator cbeg(this, 0, 0, &buckets_array_[0], firstEntry, std::vector::iterator()); + iterator cbeg(this, 0, 0, &buckets_array_[0], firstEntry, + std::vector::iterator()); return ++cbeg; } @@ -306,56 +324,60 @@ class LocalMultimap { return ++cbeg; } - key_iterator key_end() { return key_iterator::lmultimap_key_end(numBuckets_); } + key_iterator key_end() { + return key_iterator::lmultimap_key_end(numBuckets_); + } const_iterator cbegin() { return begin(); } - const_iterator cend() { return const_iterator::lmultimap_end(numBuckets_); } + const_iterator cend() { return const_iterator::lmultimap_end(numBuckets_); } void allow_inserter(size_t i) { - while (true) { - uint32_t prev_inserters = inserter_array_[i]; - - if ((prev_inserters != has_deleter) && (deleter_array_[i] == 0)) { - uint32_t new_inserters = prev_inserters + 1; - if (inserter_array_[i].compare_exchange_weak(prev_inserters, new_inserters)) { - return; - } else { - rt::impl::yield(); - } - } else { - rt::impl::yield(); - } + while (true) { + uint32_t prev_inserters = inserter_array_[i]; + + if ((prev_inserters != has_deleter) && (deleter_array_[i] == 0)) { + uint32_t new_inserters = prev_inserters + 1; + if (inserter_array_[i].compare_exchange_weak(prev_inserters, + new_inserters)) { + return; + } else { + rt::impl::yield(); + } + } else { + rt::impl::yield(); } - } + } + } - void release_inserter(size_t i) { inserter_array_[i] --; } + void release_inserter(size_t i) { inserter_array_[i]--; } - void allow_deleter(size_t i) { - deleter_array_[i] ++; + void allow_deleter(size_t i) { + deleter_array_[i]++; - while (true) { - uint32_t prev_inserters = inserter_array_[i]; - - if (prev_inserters == 0) { - if (inserter_array_[i].compare_exchange_weak(prev_inserters, has_deleter)) { - deleter_array_[i] --; - return; - } else { - rt::impl::yield(); - } - } else { - rt::impl::yield(); - } + while (true) { + uint32_t prev_inserters = inserter_array_[i]; + + if (prev_inserters == 0) { + if (inserter_array_[i].compare_exchange_weak(prev_inserters, + has_deleter)) { + deleter_array_[i]--; + return; + } else { + rt::impl::yield(); + } + } else { + rt::impl::yield(); } - } + } + } - void release_deleter(size_t i) { inserter_array_[i] = 0; } + void release_deleter(size_t i) { inserter_array_[i] = 0; } private: - static const uint8_t kHashSeed = 0; - static const size_t kAllocPending = 0x1; - static const size_t kNumEntriesPerBucket = - constants::kMMapDefaultNumEntriesPerBucket; + static const uint8_t kHashSeed = 0; + static const size_t kAllocPending = 0x1; + static const size_t kNumEntriesPerBucket = + constants::kMMapDefaultNumEntriesPerBucket; static const uint32_t kKeyWords = sizeof(KTYPE) > sizeof(uint64_t) ? sizeof(KTYPE) / sizeof(uint64_t) : 1; @@ -365,7 +387,7 @@ class LocalMultimap { struct Entry { KTYPE key; - std::vector value; + std::vector value; volatile State state; Entry() : state(EMPTY) {} }; @@ -382,12 +404,12 @@ class LocalMultimap { Entry &getEntry(size_t i) { if (!entries) { - std::lock_guard _(_entriesLock); + std::lock_guard _(_entriesLock); - if (!entries) { - entries = std::move(std::shared_ptr( - new Entry[bucketSize_], std::default_delete())); - } + if (!entries) { + entries = std::move(std::shared_ptr( + new Entry[bucketSize_], std::default_delete())); + } } return entries.get()[i]; } @@ -414,7 +436,6 @@ class LocalMultimap { const size_t i, LocalMultimap *mapPtr, ApplyFunT function, std::tuple &args, std::index_sequence) { - Bucket *bucket = &mapPtr->buckets_array_[i]; while (bucket != nullptr) { @@ -426,7 +447,7 @@ class LocalMultimap { if (entry->state == USED) { function(entry->key, entry->value, std::get(args)...); } else if (entry->state != EMPTY) { - printf( "Entry in PENDING state while iterating over entries\n"); + printf("Entry in PENDING state while iterating over entries\n"); } } @@ -436,23 +457,19 @@ class LocalMultimap { template static void ForEachEntryFunWrapper(const Tuple &args, size_t i) { - - constexpr auto Size = std::tuple_size(args))>::type>::value; + constexpr auto Size = std::tuple_size< + typename std::decay(args))>::type>::value; Tuple &tuple = const_cast(args); - CallForEachEntryFun(i, std::get<0>(tuple), - std::get<1>(tuple), std::get<2>(tuple), - std::make_index_sequence{}); + CallForEachEntryFun(i, std::get<0>(tuple), std::get<1>(tuple), + std::get<2>(tuple), std::make_index_sequence{}); } template static void AsyncCallForEachEntryFun( rt::Handle &handle, const size_t i, - LocalMultimap *mapPtr, - ApplyFunT function, std::tuple &args, - std::index_sequence) { - + LocalMultimap *mapPtr, ApplyFunT function, + std::tuple &args, std::index_sequence) { Bucket *bucket = &mapPtr->buckets_array_[i]; while (bucket != nullptr) { @@ -473,14 +490,14 @@ class LocalMultimap { } template - static void AsyncForEachEntryFunWrapper(rt::Handle &handle, - const Tuple &args, size_t i) { + static void AsyncForEachEntryFunWrapper(rt::Handle &handle, const Tuple &args, + size_t i) { constexpr auto Size = std::tuple_size< - typename std::decay(args))>::type>::value; + typename std::decay(args))>::type>::value; Tuple &tuple = const_cast(args); - AsyncCallForEachEntryFun(handle, i, std::get<0>(tuple), - std::get<1>(tuple), std::get<2>(tuple), + AsyncCallForEachEntryFun(handle, i, std::get<0>(tuple), std::get<1>(tuple), + std::get<2>(tuple), std::make_index_sequence{}); } @@ -489,7 +506,6 @@ class LocalMultimap { const size_t i, LocalMultimap *mapPtr, ApplyFunT function, std::tuple &args, std::index_sequence) { - size_t cnt = 0; Bucket *buckets_array = mapPtr->buckets_array_.data(); Bucket *bucket = &buckets_array[i]; @@ -512,19 +528,18 @@ class LocalMultimap { template static void ForEachKeyFunWrapper(const Tuple &args, size_t i) { constexpr auto Size = std::tuple_size< - typename std::decay(args))>::type>::value; + typename std::decay(args))>::type>::value; Tuple &tuple = const_cast(args); - CallForEachKeyFun(i, std::get<0>(tuple), - std::get<1>(tuple), std::get<2>(tuple), std::make_index_sequence{}); + CallForEachKeyFun(i, std::get<0>(tuple), std::get<1>(tuple), + std::get<2>(tuple), std::make_index_sequence{}); } template static void AsyncCallForEachKeyFun( rt::Handle &handle, const size_t i, - LocalMultimap *mapPtr, - ApplyFunT function, std::tuple &args, std::index_sequence) { - + LocalMultimap *mapPtr, ApplyFunT function, + std::tuple &args, std::index_sequence) { Bucket *buckets_array = mapPtr->buckets_array_.data(); Bucket *bucket = &buckets_array[i]; @@ -544,23 +559,22 @@ class LocalMultimap { } template - static void AsyncForEachKeyFunWrapper(rt::Handle &handle, - const Tuple &args, size_t i) { - constexpr auto Size = std::tuple_size< typename std::decay< - decltype(std::get<2>(args))>::type>::value; + static void AsyncForEachKeyFunWrapper(rt::Handle &handle, const Tuple &args, + size_t i) { + constexpr auto Size = std::tuple_size< + typename std::decay(args))>::type>::value; Tuple &tuple = const_cast(args); - AsyncCallForEachKeyFun(handle, i, std::get<0>(tuple), - std::get<1>(tuple), std::get<2>(tuple), std::make_index_sequence{}); + AsyncCallForEachKeyFun(handle, i, std::get<0>(tuple), std::get<1>(tuple), + std::get<2>(tuple), + std::make_index_sequence{}); } template static void AsyncCallApplyFun( - rt::Handle &handle, - LocalMultimap *mapPtr, + rt::Handle &handle, LocalMultimap *mapPtr, const KTYPE &key, ApplyFunT function, std::tuple &args, std::index_sequence) { - size_t bucketIdx = shad::hash{}(key) % mapPtr->numBuckets_; Bucket *bucket = &(mapPtr->buckets_array_[bucketIdx]); @@ -588,11 +602,10 @@ class LocalMultimap { } template - static void CallApplyFun( - LocalMultimap *mapPtr, - const KTYPE &key, ApplyFunT function, std::tuple &args, - std::index_sequence) { - + static void CallApplyFun(LocalMultimap *mapPtr, + const KTYPE &key, ApplyFunT function, + std::tuple &args, + std::index_sequence) { size_t bucketIdx = shad::hash{}(key) % mapPtr->numBuckets_; Bucket *bucket = &(mapPtr->buckets_array_[bucketIdx]); @@ -621,25 +634,24 @@ class LocalMultimap { template static void AsyncApplyFunWrapper(rt::Handle &handle, const Tuple &args) { - constexpr auto Size = std::tuple_size< typename std::decay< - decltype(std::get<3>(args))>::type>::value; + constexpr auto Size = std::tuple_size< + typename std::decay(args))>::type>::value; Tuple &tuple = const_cast(args); - AsyncCallApplyFun(handle, std::get<0>(tuple), - std::get<1>(tuple), std::get<2>(tuple), - std::get<3>(tuple), std::make_index_sequence{}); + AsyncCallApplyFun(handle, std::get<0>(tuple), std::get<1>(tuple), + std::get<2>(tuple), std::get<3>(tuple), + std::make_index_sequence{}); } }; template void LocalMultimap::AsyncLookup( - rt::Handle & handle, const KTYPE & key, LookupResult * result) { - + rt::Handle &handle, const KTYPE &key, LookupResult *result) { using LMapPtr = LocalMultimap *; auto args = std::tuple(this, key, result); - auto lookupLambda = [](rt::Handle &, const std::tuple &t) { + auto lookupLambda = [](rt::Handle &, + const std::tuple &t) { (std::get<0>(t))->Lookup(std::get<1>(t), std::get<2>(t)); }; @@ -647,16 +659,14 @@ void LocalMultimap::AsyncLookup( } template -bool LocalMultimap::Lookup(const KTYPE & key, - LookupResult * result) { - +bool LocalMultimap::Lookup(const KTYPE &key, + LookupResult *result) { size_t bucketIdx = shad::hash{}(key) % numBuckets_; - Bucket * bucket = &(buckets_array_[bucketIdx]); + Bucket *bucket = &(buckets_array_[bucketIdx]); // concurrent inserts okay; concurrent delete not okay allow_inserter(bucketIdx); - - while (bucket != nullptr) { + while (bucket != nullptr) { for (size_t i = 0; i < bucket->BucketSize(); ++i) { Entry *entry = &bucket->getEntry(i); @@ -668,19 +678,20 @@ bool LocalMultimap::Lookup(const KTYPE & key, // if key matches this entry's key, return entry's value if (KeyComp_(&entry->key, &key) == 0) { - while (!__sync_bool_compare_and_swap(&entry->state, - USED, PENDING_INSERT)) { + while (!__sync_bool_compare_and_swap(&entry->state, USED, + PENDING_INSERT)) { rt::impl::yield(); } - result->found = true; - result->size = entry->value.size(); - result->value = entry->value; + result->found = true; + result->size = entry->value.size(); + result->value = entry->value; - entry->state = USED; - release_inserter(bucketIdx); - return true; - } } + entry->state = USED; + release_inserter(bucketIdx); + return true; + } + } bucket = bucket->next.get(); } @@ -689,51 +700,50 @@ bool LocalMultimap::Lookup(const KTYPE & key, result->size = 0; release_inserter(bucketIdx); - return false; // key not found + return false; // key not found } template -void LocalMultimap::LookupFromRemote(KTYPE & key, - LookupRemoteResult * result) { - +void LocalMultimap::LookupFromRemote( + KTYPE &key, LookupRemoteResult *result) { size_t bucketIdx = shad::hash{}(key) % numBuckets_; - Bucket * bucket = &(buckets_array_[bucketIdx]); + Bucket *bucket = &(buckets_array_[bucketIdx]); // concurrent inserts okay; concurrent delete not okay allow_inserter(bucketIdx); while (bucket != nullptr) { - for (size_t i = 0; i < bucket->BucketSize(); ++i) { Entry *entry = &bucket->getEntry(i); // Reached first unused entry, key not found, return if (entry->state == EMPTY) { - result->found = false; - result->size = 0; - release_inserter(bucketIdx); + result->found = false; + result->size = 0; + release_inserter(bucketIdx); } // Wait for some other thread to finish with this entry while (entry->state == PENDING_INSERT) { - rt::impl::yield(); + rt::impl::yield(); } // if key matches this entry's key, return entry's value if (KeyComp_(&entry->key, &key) == 0) { - while (!__sync_bool_compare_and_swap(&entry->state, - USED, PENDING_INSERT)) { - rt::impl::yield(); - } - - result->found = true; - result->size = entry->value.size(); - result->remote_elems = (VTYPE *) malloc(result->size * sizeof(VTYPE)); - memcpy(result->remote_elems, entry->value.data(), - result->size * sizeof(VTYPE)); - - entry->state = USED; - release_inserter(bucketIdx); - return; - } } + while (!__sync_bool_compare_and_swap(&entry->state, USED, + PENDING_INSERT)) { + rt::impl::yield(); + } + + result->found = true; + result->size = entry->value.size(); + result->remote_elems = (VTYPE *)malloc(result->size * sizeof(VTYPE)); + memcpy(result->remote_elems, entry->value.data(), + result->size * sizeof(VTYPE)); + + entry->state = USED; + release_inserter(bucketIdx); + return; + } + } bucket = bucket->next.get(); } @@ -747,22 +757,21 @@ void LocalMultimap::LookupFromRemote(KTYPE & key, template void LocalMultimap::PrintAllEntries() { - - for (auto itr = begin(); itr != end(); ++ itr) { - auto key = (* itr).first; - std::cout << std::get<0>(key) << " " << std::get<1>(key); - std::cout << "\n"; + for (auto itr = begin(); itr != end(); ++itr) { + auto key = (*itr).first; + std::cout << std::get<0>(key) << " " << std::get<1>(key); + std::cout << "\n"; } } template void LocalMultimap::PrintAllKeys() { - - for (auto itr = key_begin(); itr != key_end(); ++ itr) { - auto key = (* itr).first; - auto value = (* itr).second; - std::cout << value.size() << " " << std::get<0>(key) << " " << std::get<1>(key); - std::cout << "\n"; + for (auto itr = key_begin(); itr != key_end(); ++itr) { + auto key = (*itr).first; + auto value = (*itr).second; + std::cout << value.size() << " " << std::get<0>(key) << " " + << std::get<1>(key); + std::cout << "\n"; } } @@ -776,10 +785,13 @@ void LocalMultimap::Erase(const KTYPE &key) { for (;;) { // loop over entries in this bucket for (size_t i = 0; i < bucket->BucketSize(); ++i) { - Entry * entry = &bucket->getEntry(i); + Entry *entry = &bucket->getEntry(i); // Reached first unused entry, key not found, return - if (entry->state == EMPTY) { release_deleter(bucketIdx); return; } + if (entry->state == EMPTY) { + release_deleter(bucketIdx); + return; + } // If key does not match this entry's key, continue inner for loop if (KeyComp_(&entry->key, &key) != 0) continue; @@ -792,58 +804,61 @@ void LocalMultimap::Erase(const KTYPE &key) { // lastEntry == last entry in this bucket // nextEntry == first unused entry in this bucket - Entry * lastEntry = entry; + Entry *lastEntry = entry; size_t j = i + 1; // loop over linked buckets for (;;) { // loop over entries in this bucket - for ( ; j < bucket->BucketSize(); ++j) { - Entry * nextEntry = & bucket->getEntry(j); - if (nextEntry->state == USED) {lastEntry = nextEntry; continue;} - - // entry is last entry, so set it to empty - if (entry == lastEntry) { - entry->state = EMPTY; - std::swap(entry->value, emptyValue); - release_deleter(bucketIdx); - return; - - // set entry {key, value} to lastEntry {key, value} + for (; j < bucket->BucketSize(); ++j) { + Entry *nextEntry = &bucket->getEntry(j); + if (nextEntry->state == USED) { + lastEntry = nextEntry; + continue; + } + + // entry is last entry, so set it to empty + if (entry == lastEntry) { + entry->state = EMPTY; + std::swap(entry->value, emptyValue); + release_deleter(bucketIdx); + return; + + // set entry {key, value} to lastEntry {key, value} // and set lastEntry to empty - } else { - entry->key = std::move(lastEntry->key); - entry->value = std::move(lastEntry->value); - - lastEntry->state = EMPTY; - std::swap(lastEntry->value, emptyValue); - release_deleter(bucketIdx); - return; - } - } // Second inner for loop + } else { + entry->key = std::move(lastEntry->key); + entry->value = std::move(lastEntry->value); + + lastEntry->state = EMPTY; + std::swap(lastEntry->value, emptyValue); + release_deleter(bucketIdx); + return; + } + } // Second inner for loop // Exhausted linked buckets, so lastEntry is last USED entry if (bucket->next == nullptr) { - entry->key = std::move(lastEntry->key); - entry->value = std::move(lastEntry->value); + entry->key = std::move(lastEntry->key); + entry->value = std::move(lastEntry->value); - lastEntry->state = EMPTY; - std::swap(lastEntry->value, emptyValue); - release_deleter(bucketIdx); - return; + lastEntry->state = EMPTY; + std::swap(lastEntry->value, emptyValue); + release_deleter(bucketIdx); + return; } else { - bucket = bucket->next.get(); + bucket = bucket->next.get(); } - } // Second outer for loop - } // First inner for loop + } // Second outer for loop + } // First inner for loop // Exhausted linked buckets without finding key, return if (bucket->next == nullptr) { - release_deleter(bucketIdx); - return; + release_deleter(bucketIdx); + return; } else { - bucket = bucket->next.get(); + bucket = bucket->next.get(); } - } // First outer for loop + } // First outer for loop } template @@ -864,53 +879,55 @@ std::pair::iterator, bool> LocalMultimap::Insert(const KTYPE &key, const VTYPE &value) { size_t bucketIdx = shad::hash{}(key) % numBuckets_; - Bucket * bucket = &(buckets_array_[bucketIdx]); + Bucket *bucket = &(buckets_array_[bucketIdx]); allow_inserter(bucketIdx); // loop over linked buckets for (;;) { // loop over entries in this bucket for (size_t i = 0; i < bucket->BucketSize(); ++i) { - Entry *entry = & bucket->getEntry(i); + Entry *entry = &bucket->getEntry(i); // Reached end of used entries without finding key, so new key if (__sync_bool_compare_and_swap(&entry->state, EMPTY, PENDING_INSERT)) { - entry->key = std::move(key); - entry->value.push_back(value); - - size_ += 1; - entry->state = USED; - release_inserter(bucketIdx); - return std::make_pair(iterator(this, bucketIdx, i, bucket, entry, - entry->value.end() - 1), true); + entry->key = std::move(key); + entry->value.push_back(value); + + size_ += 1; + entry->state = USED; + release_inserter(bucketIdx); + return std::make_pair( + iterator(this, bucketIdx, i, bucket, entry, entry->value.end() - 1), + true); } // Wait for some other thread to finish with this entry while (entry->state == PENDING_INSERT) rt::impl::yield(); - // if key matches this entry's key, insert value; else continue inner for loop + // if key matches this entry's key, insert value; else continue inner for + // loop if (KeyComp_(&entry->key, &key) == 0) { - while (!__sync_bool_compare_and_swap(&entry->state, - USED, PENDING_INSERT)) { - rt::impl::yield(); - } - entry->value.push_back(value); - - size_ += 1; - entry->state = USED; - release_inserter(bucketIdx); - return std::make_pair(iterator(this, bucketIdx, i, bucket, entry, - entry->value.end() - 1), true); + while (!__sync_bool_compare_and_swap(&entry->state, USED, + PENDING_INSERT)) { + rt::impl::yield(); + } + entry->value.push_back(value); + + size_ += 1; + entry->state = USED; + release_inserter(bucketIdx); + return std::make_pair( + iterator(this, bucketIdx, i, bucket, entry, entry->value.end() - 1), + true); } - } // Inner for loop + } // Inner for loop // Exhausted entries in this buckets // ... if no more buckets, link new bucket if (bucket->next == nullptr) { - if (__sync_bool_compare_and_swap(&bucket->isNextAllocated, - false, true)) { - // Allocate new bucket + if (__sync_bool_compare_and_swap(&bucket->isNextAllocated, false, true)) { + // Allocate new bucket std::shared_ptr newBucket( - new Bucket(constants::kMMapDefaultNumEntriesPerBucket)); + new Bucket(constants::kMMapDefaultNumEntriesPerBucket)); bucket->next.swap(newBucket); } else { // Wait for pending allocation to finish @@ -920,13 +937,13 @@ LocalMultimap::Insert(const KTYPE &key, // move to next bucket bucket = bucket->next.get(); - } // Outer for loop + } // Outer for loop } template -void LocalMultimap::AsyncInsert( - rt::Handle &handle, const KTYPE &key, const VTYPE &value) { - +void LocalMultimap::AsyncInsert(rt::Handle &handle, + const KTYPE &key, + const VTYPE &value) { using LMapPtr = LocalMultimap *; auto args = std::tuple(this, key, value); @@ -940,25 +957,22 @@ void LocalMultimap::AsyncInsert( template template -void LocalMultimap::ForEachEntry(ApplyFunT &&function, - Args &... args) { - +void LocalMultimap::ForEachEntry( + ApplyFunT &&function, Args &...args) { using FunctionTy = void (*)(const KTYPE &, VTYPE &, Args &...); FunctionTy fn = std::forward(function); using LMapPtr = LocalMultimap *; using ArgsTuple = std::tuple>; ArgsTuple argsTuple(this, fn, std::tuple(args...)); - rt::forEachAt(rt::thisLocality(), - ForEachEntryFunWrapper, - argsTuple, numBuckets_); + rt::forEachAt(rt::thisLocality(), ForEachEntryFunWrapper, + argsTuple, numBuckets_); } template template void LocalMultimap::AsyncForEachEntry( - rt::Handle &handle, ApplyFunT &&function, Args &... args) { - + rt::Handle &handle, ApplyFunT &&function, Args &...args) { using FunctionTy = void (*)(rt::Handle &, const KTYPE &, VTYPE &, Args &...); FunctionTy fn = std::forward(function); using LMapPtr = LocalMultimap *; @@ -966,14 +980,14 @@ void LocalMultimap::AsyncForEachEntry( ArgsTuple argsTuple(this, fn, std::tuple(args...)); rt::asyncForEachAt(handle, rt::thisLocality(), - AsyncForEachEntryFunWrapper, argsTuple, numBuckets_); + AsyncForEachEntryFunWrapper, argsTuple, + numBuckets_); } template template void LocalMultimap::ForEachKey(ApplyFunT &&function, - Args &... args) { - + Args &...args) { using FunctionTy = void (*)(const KTYPE &, Args &...); FunctionTy fn = std::forward(function); using LMapPtr = LocalMultimap *; @@ -987,8 +1001,7 @@ void LocalMultimap::ForEachKey(ApplyFunT &&function, template template void LocalMultimap::AsyncForEachKey( - rt::Handle &handle, ApplyFunT &&function, Args &... args) { - + rt::Handle &handle, ApplyFunT &&function, Args &...args) { using FunctionTy = void (*)(rt::Handle &, const KTYPE &, Args &...); FunctionTy fn = std::forward(function); using LMapPtr = LocalMultimap *; @@ -996,18 +1009,21 @@ void LocalMultimap::AsyncForEachKey( ArgsTuple argsTuple(this, fn, std::tuple(args...)); rt::asyncForEachAt(handle, rt::thisLocality(), - AsyncForEachKeyFunWrapper, argsTuple, numBuckets_); + AsyncForEachKeyFunWrapper, argsTuple, + numBuckets_); } template template -void LocalMultimap::AsyncApply( - rt::Handle &handle, const KTYPE &key, ApplyFunT &&function, Args &... args) { - +void LocalMultimap::AsyncApply(rt::Handle &handle, + const KTYPE &key, + ApplyFunT &&function, + Args &...args) { using FunctionTy = void (*)(rt::Handle &, const KTYPE &, VTYPE &, Args &...); FunctionTy fn = std::forward(function); using LMapPtr = LocalMultimap *; - using ArgsTuple = std::tuple>; + using ArgsTuple = + std::tuple>; ArgsTuple argsTuple(this, key, fn, std::tuple(args...)); rt::asyncExecuteAt(handle, rt::thisLocality(), @@ -1030,42 +1046,43 @@ LocalMultimap::Insert(const KTYPE &key, // Reached end of used entries without finding key, so new key if (__sync_bool_compare_and_swap(&entry->state, EMPTY, PENDING_INSERT)) { - entry->key = std::move(key); - entry->value.push_back(value); - - size_ += 1; - entry->state = USED; - release_inserter(bucketIdx); - return std::make_pair(iterator(this, bucketIdx, i, bucket, entry), true); + entry->key = std::move(key); + entry->value.push_back(value); + + size_ += 1; + entry->state = USED; + release_inserter(bucketIdx); + return std::make_pair(iterator(this, bucketIdx, i, bucket, entry), + true); } // Wait for some other thread to finish with this entry while (entry->state == PENDING_INSERT) rt::impl::yield(); - //if key matches entry's key, insert value; else continue inner for loop + // if key matches entry's key, insert value; else continue inner for loop if (KeyComp_(&entry->key, &key) == 0) { - while (!__sync_bool_compare_and_swap(&entry->state, - USED, PENDING_INSERT)) { - rt::impl::yield(); - } - entry->value.push_back(value); - - size_ += 1; - entry->state = USED; - release_inserter(bucketIdx); - return std::make_pair(iterator(this, bucketIdx, i, bucket, entry), true); + while (!__sync_bool_compare_and_swap(&entry->state, USED, + PENDING_INSERT)) { + rt::impl::yield(); + } + entry->value.push_back(value); + + size_ += 1; + entry->state = USED; + release_inserter(bucketIdx); + return std::make_pair(iterator(this, bucketIdx, i, bucket, entry), + true); } - } // Inner for loop + } // Inner for loop // Exhausted linked buckets, so link new bucket // Exhausted entries in this buckets // ... if no more buckets, link new bucket if (bucket->next == nullptr) { - if (__sync_bool_compare_and_swap(&bucket->isNextAllocated, - false, true)) { + if (__sync_bool_compare_and_swap(&bucket->isNextAllocated, false, true)) { // Allocate new bucket std::shared_ptr newBucket( - new Bucket(constants::kMMapDefaultNumEntriesPerBucket)); + new Bucket(constants::kMMapDefaultNumEntriesPerBucket)); bucket->next.swap(newBucket); } else { // Wait for pending allocation to finish @@ -1075,18 +1092,18 @@ LocalMultimap::Insert(const KTYPE &key, // move to next bucket bucket = bucket->next.get(); - } // Outer for loop + } // Outer for loop } template template void LocalMultimap::AsyncInsert( rt::Handle &handle, const KTYPE &key, const ELTYPE &value) { - using LMapPtr = LocalMultimap *; auto args = std::tuple(this, key, value); - auto insertLambda = [](rt::Handle &, const std::tuple &t) { + auto insertLambda = [](rt::Handle &, + const std::tuple &t) { (std::get<0>(t))->Insert(std::get<1>(t), std::get<2>(t)); }; @@ -1100,13 +1117,14 @@ class lmultimap_iterator : public std::iterator { public: using inner_type = typename LMap::inner_type; - using Entry = typename LMap::Entry; - using State = typename LMap::State; + using Entry = typename LMap::Entry; + using State = typename LMap::State; using Bucket = typename LMap::Bucket; lmultimap_iterator() {} - lmultimap_iterator(const LMap *mapPtr, size_t bId, - size_t pos, Bucket *cb, Entry *ePtr, typename std::vector::iterator valueItr) + lmultimap_iterator(const LMap *mapPtr, size_t bId, size_t pos, Bucket *cb, + Entry *ePtr, + typename std::vector::iterator valueItr) : mapPtr_(mapPtr), bucketId_(bId), position_(pos), @@ -1117,8 +1135,12 @@ class lmultimap_iterator : public std::iterator { static lmultimap_iterator lmultimap_begin(const LMap *mapPtr) { Bucket *rootPtr = &(const_cast(mapPtr)->buckets_array_[0]); Entry *firstEntry = &(rootPtr->getEntry(0)); - lmultimap_iterator beg(mapPtr, 0, 0, rootPtr, firstEntry, firstEntry->value.begin()); - if (firstEntry->state == LMap::USED) return beg; else return ++beg; + lmultimap_iterator beg(mapPtr, 0, 0, rootPtr, firstEntry, + firstEntry->value.begin()); + if (firstEntry->state == LMap::USED) + return beg; + else + return ++beg; } static lmultimap_iterator lmultimap_end(const LMap *mapPtr) { @@ -1126,7 +1148,8 @@ class lmultimap_iterator : public std::iterator { } static lmultimap_iterator lmultimap_end(size_t numBuckets) { - return lmultimap_iterator(nullptr, numBuckets, 0, nullptr, nullptr, typename std::vector::iterator()); + return lmultimap_iterator(nullptr, numBuckets, 0, nullptr, nullptr, + typename std::vector::iterator()); } bool operator==(const lmultimap_iterator &other) const { @@ -1137,71 +1160,79 @@ class lmultimap_iterator : public std::iterator { return !(*this == other); } - T operator*() const { return T(entryPtr_->key, * valueItr_); } + T operator*() const { return T(entryPtr_->key, *valueItr_); } -// Returns the key and value of the next value vector entry; -// Entry values are stored in a four-level data structure --- -// for each bucket list ... for each bucket in list ... -// for each entry in bucket ... for each value in entry's value array + // Returns the key and value of the next value vector entry; + // Entry values are stored in a four-level data structure --- + // for each bucket list ... for each bucket in list ... + // for each entry in bucket ... for each value in entry's value + // array lmultimap_iterator &operator++() { auto null_iter = std::vector::iterator(); - // if iterator points to an VTYPE, move to next VTYPE; else move to next bucket list + // if iterator points to an VTYPE, move to next VTYPE; else move to next + // bucket list if (valueItr_ != null_iter) { - ++ valueItr_; - - // if there is another VTYPE in entry's value array, return it - if (valueItr_ != entryPtr_->value.end()) return * this; - - // ... else move to next entry in bucket - ++ position_; - - // if there is another entry in this bucket ... - //FIXME - if (position_ < constants::kMMapDefaultNumEntriesPerBucket) { - entryPtr_ ++; - - // if this entry is used, return begin of its value array - // ... else no more entries in this bucket or buckets in this bucket list - if (entryPtr_->state == LMap::USED) { - valueItr_ = entryPtr_->value.begin(); return * this; - } - - // ... else move to next bucket in this bucket list - } else { - currBucket_ = currBucket_->next.get(); - position_ = 0; - - // if bucket is not empty and first entry is used, return begin of its value array - // ... else no more entries in this bucket or buckets in this bucket list - if (currBucket_ != nullptr) { - entryPtr_ = &currBucket_->getEntry(position_); - if (entryPtr_->state == LMap::USED) { - valueItr_ = entryPtr_->value.begin(); return * this; - } + ++valueItr_; + + // if there is another VTYPE in entry's value array, return it + if (valueItr_ != entryPtr_->value.end()) return *this; + + // ... else move to next entry in bucket + ++position_; + + // if there is another entry in this bucket ... + // FIXME + if (position_ < constants::kMMapDefaultNumEntriesPerBucket) { + entryPtr_++; + + // if this entry is used, return begin of its value array + // ... else no more entries in this bucket or buckets in this bucket + // list + if (entryPtr_->state == LMap::USED) { + valueItr_ = entryPtr_->value.begin(); + return *this; + } + + // ... else move to next bucket in this bucket list + } else { + currBucket_ = currBucket_->next.get(); + position_ = 0; + + // if bucket is not empty and first entry is used, return begin of its + // value array + // ... else no more entries in this bucket or buckets in this bucket + // list + if (currBucket_ != nullptr) { + entryPtr_ = &currBucket_->getEntry(position_); + if (entryPtr_->state == LMap::USED) { + valueItr_ = entryPtr_->value.begin(); + return *this; } - } + } + } } // move to next bucket list - ++ bucketId_; + ++bucketId_; position_ = 0; // search for a bucket list with a used entry - for ( ; bucketId_ < mapPtr_->numBuckets_; ++bucketId_) { - currBucket_ = & const_cast(mapPtr_)->buckets_array_[bucketId_]; - entryPtr_ = & currBucket_->getEntry(position_); - if (entryPtr_->state == LMap::USED) { - valueItr_ = entryPtr_->value.begin(); return *this; - } + for (; bucketId_ < mapPtr_->numBuckets_; ++bucketId_) { + currBucket_ = &const_cast(mapPtr_)->buckets_array_[bucketId_]; + entryPtr_ = &currBucket_->getEntry(position_); + if (entryPtr_->state == LMap::USED) { + valueItr_ = entryPtr_->value.begin(); + return *this; + } } // next is not found, return end iterator - mapPtr_ = nullptr; - entryPtr_ = nullptr; + mapPtr_ = nullptr; + entryPtr_ = nullptr; currBucket_ = nullptr; - valueItr_ = std::vector::iterator(); - return * this; + valueItr_ = std::vector::iterator(); + return *this; } lmultimap_iterator operator++(int) { @@ -1212,10 +1243,11 @@ class lmultimap_iterator : public std::iterator { class partition_range { public: - partition_range(const lmultimap_iterator &begin, const lmultimap_iterator &end) + partition_range(const lmultimap_iterator &begin, + const lmultimap_iterator &end) : begin_(begin), end_(end) {} lmultimap_iterator begin() { return begin_; } - lmultimap_iterator end() { return end_; } + lmultimap_iterator end() { return end_; } private: lmultimap_iterator begin_; @@ -1230,12 +1262,12 @@ class lmultimap_iterator : public std::iterator { auto n_buckets = n_spanned_buckets(begin, end); if (n_buckets && n_parts) { - auto part_step = (n_buckets >= n_parts) - ? (n_buckets + n_parts - 1) / n_parts : 1; + auto part_step = + (n_buckets >= n_parts) ? (n_buckets + n_parts - 1) / n_parts : 1; auto map_ptr = begin.mapPtr_; auto &buckets = map_ptr->buckets_array_; - auto b_end = (end != lmultimap_end(map_ptr)) - ? end.bucketId_ : map_ptr->numBuckets_; + auto b_end = (end != lmultimap_end(map_ptr)) ? end.bucketId_ + : map_ptr->numBuckets_; auto bi = begin.bucketId_; auto pbegin = begin; @@ -1260,7 +1292,7 @@ class lmultimap_iterator : public std::iterator { size_t bucketId_; size_t position_; Bucket *currBucket_; - Entry *entryPtr_; + Entry *entryPtr_; typename std::vector::iterator valueItr_; // returns a pointer to the first entry of a bucket @@ -1282,7 +1314,6 @@ class lmultimap_iterator : public std::iterator { // returns the index of the first active bucket, starting from the input // bucket (included). If not such bucket, it returns the number of buckets. static size_t first_used_bucket(const LMap *mapPtr_, size_t bi) { - // scan for the first used entry with the same logic as operator++ for (; bi < mapPtr_->numBuckets_; ++bi) if (first_bucket_entry(mapPtr_, bi).state == LMap::USED) return bi; @@ -1293,7 +1324,6 @@ class lmultimap_iterator : public std::iterator { // returns the number of buckets spanned by the input range static size_t n_spanned_buckets(const lmultimap_iterator &begin, const lmultimap_iterator &end) { - if (begin != end) { auto map_ptr = begin.mapPtr_; @@ -1304,8 +1334,8 @@ class lmultimap_iterator : public std::iterator { if (end != lmultimap_end(map_ptr)) { // count one more if end is not on a bucket edge return end.bucketId_ - begin.bucketId_ + - (end.entryPtr_ != &first_bucket_entry(end.mapPtr_, - end.bucketId_)); + (end.entryPtr_ != + &first_bucket_entry(end.mapPtr_, end.bucketId_)); } return map_ptr->numBuckets_ - begin.bucketId_; @@ -1315,20 +1345,20 @@ class lmultimap_iterator : public std::iterator { }; template -class lmultimap_key_iterator : - public std::iterator { +class lmultimap_key_iterator + : public std::iterator { template friend class multimap_key_iterator; public: using inner_type = typename LMap::inner_type; - using Entry = typename LMap::Entry; - using State = typename LMap::State; + using Entry = typename LMap::Entry; + using State = typename LMap::State; using Bucket = typename LMap::Bucket; lmultimap_key_iterator() {} - lmultimap_key_iterator(const LMap *mapPtr, size_t bId, size_t pos, - Bucket *cb, Entry *ePtr) + lmultimap_key_iterator(const LMap *mapPtr, size_t bId, size_t pos, Bucket *cb, + Entry *ePtr) : mapPtr_(mapPtr), bucketId_(bId), position_(pos), @@ -1339,7 +1369,10 @@ class lmultimap_key_iterator : Bucket *rootPtr = &(const_cast(mapPtr)->buckets_array_[0]); Entry *firstEntry = &(rootPtr->getEntry(0)); lmultimap_key_iterator beg(mapPtr, 0, 0, rootPtr, firstEntry); - if (firstEntry->state == LMap::USED) return beg; else return ++beg; + if (firstEntry->state == LMap::USED) + return beg; + else + return ++beg; } static lmultimap_key_iterator lmultimap_key_end(const LMap *mapPtr) { @@ -1360,51 +1393,51 @@ class lmultimap_key_iterator : T operator*() const { return T(entryPtr_->key, entryPtr_->value); } -// Returns next entry (a pointer to {KEY, VALUE}; -// Entries are stored in three-level data structure --- -// for each bucket list ... for each bucket in list -// ... for each entry in bucket + // Returns next entry (a pointer to {KEY, VALUE}; + // Entries are stored in three-level data structure --- + // for each bucket list ... for each bucket in list + // ... for each entry in bucket lmultimap_key_iterator &operator++() { // move to next entry in bucket - ++ position_; + ++position_; // if there is another entry in this bucket ... if (position_ < constants::kMMapDefaultNumEntriesPerBucket) { - entryPtr_ ++; + entryPtr_++; - // if this entry is used, return it - // ... else no more entries in this bucket or buckets in this bucket list - if (entryPtr_->state == LMap::USED) return * this; + // if this entry is used, return it + // ... else no more entries in this bucket or buckets in this bucket list + if (entryPtr_->state == LMap::USED) return *this; - // ... else move to next bucket in this bucket list + // ... else move to next bucket in this bucket list } else { - currBucket_ = currBucket_->next.get(); - position_ = 0; - - // if bucket is not empty and first entry is used, return it - // ... else no more entries in this bucket or buckets in this bucket list - if (currBucket_ != nullptr) { - entryPtr_ = &currBucket_->getEntry(position_); - if (entryPtr_->state == LMap::USED) return * this; - } + currBucket_ = currBucket_->next.get(); + position_ = 0; + + // if bucket is not empty and first entry is used, return it + // ... else no more entries in this bucket or buckets in this bucket list + if (currBucket_ != nullptr) { + entryPtr_ = &currBucket_->getEntry(position_); + if (entryPtr_->state == LMap::USED) return *this; + } } // move to next bucket list - ++ bucketId_; + ++bucketId_; position_ = 0; // search for a bucket list with a used entity - for ( ; bucketId_ < mapPtr_->numBuckets_; ++bucketId_) { - currBucket_ = & const_cast(mapPtr_)->buckets_array_[bucketId_]; - entryPtr_ = & currBucket_->getEntry(position_); - if (entryPtr_->state == LMap::USED) return * this; + for (; bucketId_ < mapPtr_->numBuckets_; ++bucketId_) { + currBucket_ = &const_cast(mapPtr_)->buckets_array_[bucketId_]; + entryPtr_ = &currBucket_->getEntry(position_); + if (entryPtr_->state == LMap::USED) return *this; } // next is not found, return end iterator - mapPtr_ = nullptr; - entryPtr_ = nullptr; + mapPtr_ = nullptr; + entryPtr_ = nullptr; currBucket_ = nullptr; - return * this; + return *this; } lmultimap_key_iterator operator++(int) { @@ -1419,7 +1452,7 @@ class lmultimap_key_iterator : const lmultimap_key_iterator &end) : begin_(begin), end_(end) {} lmultimap_key_iterator begin() { return begin_; } - lmultimap_key_iterator end() { return end_; } + lmultimap_key_iterator end() { return end_; } private: lmultimap_key_iterator begin_; @@ -1434,12 +1467,12 @@ class lmultimap_key_iterator : auto n_buckets = n_spanned_buckets(begin, end); if (n_buckets && n_parts) { - auto part_step = (n_buckets >= n_parts) - ? (n_buckets + n_parts - 1) / n_parts : 1; + auto part_step = + (n_buckets >= n_parts) ? (n_buckets + n_parts - 1) / n_parts : 1; auto map_ptr = begin.mapPtr_; auto &buckets = map_ptr->buckets_array_; - auto b_end = (end != lmultimap_key_end(map_ptr)) - ? end.bucketId_ : map_ptr->numBuckets_; + auto b_end = (end != lmultimap_key_end(map_ptr)) ? end.bucketId_ + : map_ptr->numBuckets_; auto bi = begin.bucketId_; auto pbegin = begin; @@ -1466,7 +1499,7 @@ class lmultimap_key_iterator : size_t bucketId_; size_t position_; Bucket *currBucket_; - Entry *entryPtr_; + Entry *entryPtr_; // returns a pointer to the first entry of a bucket static typename LMap::Entry &first_bucket_entry(const LMap *mapPtr_, @@ -1474,21 +1507,20 @@ class lmultimap_key_iterator : return const_cast(mapPtr_)->buckets_array_[bi].getEntry(0); } - // returns an iterator pointing to the beginning + // returns an iterator pointing to the beginning // of the first active bucket from the input bucket (included) static lmultimap_key_iterator first_in_bucket(const LMap *mapPtr_, size_t bi) { auto &entry = first_bucket_entry(mapPtr_, bi); - return lmultimap_key_iterator(mapPtr_, bi, 0, - &const_cast(mapPtr_)->buckets_array_[bi], - &entry); + return lmultimap_key_iterator( + mapPtr_, bi, 0, &const_cast(mapPtr_)->buckets_array_[bi], + &entry); } // returns the index of the first active bucket, starting from the input // bucket (included). If not such bucket, it returns the number of buckets. static size_t first_used_bucket(const LMap *mapPtr_, size_t bi) { - // scan for the first used entry with the same logic as operator++ for (; bi < mapPtr_->numBuckets_; ++bi) if (first_bucket_entry(mapPtr_, bi).state == LMap::USED) return bi; @@ -1499,7 +1531,6 @@ class lmultimap_key_iterator : // returns the number of buckets spanned by the input range static size_t n_spanned_buckets(const lmultimap_key_iterator &begin, const lmultimap_key_iterator &end) { - if (begin != end) { auto map_ptr = begin.mapPtr_; @@ -1510,8 +1541,8 @@ class lmultimap_key_iterator : if (end != lmultimap_key_end(map_ptr)) { // count one more if end is not on a bucket edge return end.bucketId_ - begin.bucketId_ + - (end.entryPtr_ != &first_bucket_entry(end.mapPtr_, - end.bucketId_)); + (end.entryPtr_ != + &first_bucket_entry(end.mapPtr_, end.bucketId_)); } return map_ptr->numBuckets_ - begin.bucketId_; diff --git a/include/shad/data_structures/multimap.h b/include/shad/data_structures/multimap.h index 2eea4e9e..df7a57d6 100644 --- a/include/shad/data_structures/multimap.h +++ b/include/shad/data_structures/multimap.h @@ -26,13 +26,13 @@ #define INCLUDE_SHAD_DATA_STRUCTURES_MULTIMAP_H_ #include +#include #include -#include +#include #include -#include +#include #include -#include -#include +#include #include "shad/data_structures/abstract_data_structure.h" #include "shad/data_structures/buffer.h" @@ -40,7 +40,6 @@ #include "shad/data_structures/local_multimap.h" #include "shad/distributed_iterator_traits.h" #include "shad/runtime/runtime.h" -#include "shad/runtime/mappings/gmt/gmt_synchronous_interface.h" #define PREFIX_SIZE 80 @@ -56,17 +55,17 @@ class multimap_iterator; /// @tparam VTYPE type of the multimap values. /// @tparam KEY_COMPARE key comparison function; default is MemCmp. /// @warning obects of type KTYPE and VTYPE need to be trivially copiable. -template < typename KTYPE, typename VTYPE, typename KEY_COMPARE = MemCmp > -class Multimap : public AbstractDataStructure< Multimap > { - +template > +class Multimap + : public AbstractDataStructure> { template friend class AbstractDataStructure; friend class multimap_iterator, - const std::pair, - std::pair>; + const std::pair, + std::pair>; friend class multimap_iterator, - const std::pair, - std::pair>; + const std::pair, + std::pair>; public: using value_type = std::pair; @@ -77,16 +76,16 @@ class Multimap : public AbstractDataStructure< Multimap, - const std::pair, std::pair>; + const std::pair, std::pair>; using const_iterator = multimap_iterator, - const std::pair, std::pair>; + const std::pair, std::pair>; using local_iterator = lmultimap_iterator, - const std::pair>; + const std::pair>; using const_local_iterator = lmultimap_iterator, - const std::pair>; + const std::pair>; struct EntryT { EntryT(const KTYPE &k, const VTYPE &v) : key(k), value(v) {} @@ -126,7 +125,8 @@ class Multimap : public AbstractDataStructure< Multimap::LookupResult; - using LookupRemoteResult = typename LocalMultimap::LookupRemoteResult; + using LookupResult = + typename LocalMultimap::LookupResult; + using LookupRemoteResult = + typename LocalMultimap::LookupRemoteResult; /// @brief Get all the values associated to a key. /// @param[in] key the key. - /// @param[out] res a pointer to the values if the the key-value was found, otherwise NULL + /// @param[out] res a pointer to the values if the the key-value was found, + /// otherwise NULL /// @return true if the entry is found, otherwise false bool Lookup(const KTYPE &key, LookupResult *res); /// @brief Asynchronous lookup method. /// @warning Asynchronous operations are guaranteed to have completed. /// only after calling the rt::waitForCompletion(rt::Handle &handle) method. - /// @param[in,out] handle Reference to the handle to be used to wait for completion. + /// @param[in,out] handle Reference to the handle to be used to wait for + /// completion. /// @param[in] key the key. /// @param[out] res the result of the lookup operation. void AsyncLookup(rt::Handle &handle, const KTYPE &key, LookupResult *res); - /// @brief Read records from multiple files - /// @param[in] prefix the file prefix - /// @param[in] lb the lower bound postscript - /// @param[in] ub the upper bound postscript - void readFromFiles(rt::Handle & handle, std::string prefix, uint64_t lb, uint64_t ub); - /// @brief Apply a user-defined function to a key-value pair. /// - /// @tparam ApplyFunT User-defined function type. The function prototype should be: + /// @tparam ApplyFunT User-defined function type. The function prototype + /// should be: /// @code /// void(const KTYPE&, VTYPE&, Args&); /// @endcode @@ -213,11 +215,12 @@ class Multimap : public AbstractDataStructure< Multimap - void Apply(const KTYPE &key, ApplyFunT &&function, Args &... args); + void Apply(const KTYPE &key, ApplyFunT &&function, Args &...args); /// @brief Asynchronously apply a user-defined function to a key-value pair. /// - /// @tparam ApplyFunT User-defined function type. The function prototype should be: + /// @tparam ApplyFunT User-defined function type. The function prototype + /// should be: /// @code /// void(rt::Handle &handle, const KTYPE&, VTYPE&, Args&); /// @endcode @@ -229,11 +232,12 @@ class Multimap : public AbstractDataStructure< Multimap void AsyncApply(rt::Handle &handle, const KTYPE &key, ApplyFunT &&function, - Args &... args); + Args &...args); /// @brief Apply a user-defined function to each key-value pair. /// - /// @tparam ApplyFunT User-defined function type. The function prototype should be: + /// @tparam ApplyFunT User-defined function type. The function prototype + /// should be: /// @code /// void(const KTYPE&, VTYPE&, Args&); /// @endcode @@ -242,11 +246,13 @@ class Multimap : public AbstractDataStructure< Multimap - void ForEachEntry(ApplyFunT &&function, Args &... args); + void ForEachEntry(ApplyFunT &&function, Args &...args); - /// @brief Asynchronously apply a user-defined function to each key-value pair. + /// @brief Asynchronously apply a user-defined function to each key-value + /// pair. /// - /// @tparam ApplyFunT User-defined function type. he function prototype should be: + /// @tparam ApplyFunT User-defined function type. he function prototype + /// should be: /// @code /// void(shad::rt::Handle&, const KTYPE&, VTYPE&, Args&); /// @endcode @@ -256,11 +262,13 @@ class Multimap : public AbstractDataStructure< Multimap - void AsyncForEachEntry(rt::Handle &handle, ApplyFunT &&function, Args &... args); + void AsyncForEachEntry(rt::Handle &handle, ApplyFunT &&function, + Args &...args); /// @brief Apply a user-defined function to each key. /// - /// @tparam ApplyFunT User-defined function type. The function prototype should be: + /// @tparam ApplyFunT User-defined function type. The function prototype + /// should be: /// @code /// void(const KTYPE&, Args&); /// @endcode @@ -269,11 +277,12 @@ class Multimap : public AbstractDataStructure< Multimap - void ForEachKey(ApplyFunT &&function, Args &... args); + void ForEachKey(ApplyFunT &&function, Args &...args); /// @brief Asynchronously apply a user-defined function to each key. /// - /// @tparam ApplyFunT User-defined function type. The function prototype should be: + /// @tparam ApplyFunT User-defined function type. The function prototype + /// should be: /// @code /// void(shad::rt::Handle&, const KTYPE&, Args&); /// @endcode @@ -283,24 +292,28 @@ class Multimap : public AbstractDataStructure< Multimap - void AsyncForEachKey(rt::Handle &handle, ApplyFunT &&function, Args &... args); + void AsyncForEachKey(rt::Handle &handle, ApplyFunT &&function, Args &...args); void PrintAllEntries() { - auto printLambda = [](const ObjectID & oid) { + auto printLambda = [](const ObjectID &oid) { auto mapPtr = HmapT::GetPtr(oid); mapPtr->localMultimap_.PrintAllEntries(); }; - for (auto loc : rt::allLocalities()) rt::executeAt(loc, printLambda, oid_); + for (auto loc : rt::allLocalities()) { + rt::executeAt(loc, printLambda, oid_); + } } void PrintAllKeys() { - auto printLambda = [](const ObjectID & oid) { + auto printLambda = [](const ObjectID &oid) { auto mapPtr = HmapT::GetPtr(oid); mapPtr->localMultimap_.PrintAllKeys(); }; - for (auto loc : rt::allLocalities()) rt::executeAt(loc, printLambda, oid_); + for (auto loc : rt::allLocalities()) { + rt::executeAt(loc, printLambda, oid_); + } } // FIXME it should be protected @@ -317,7 +330,9 @@ class Multimap : public AbstractDataStructure< Multimap::Size() const { } template -inline std::pair < typename Multimap::iterator, bool > -Multimap::Insert(const KTYPE &key, const VTYPE &value) { +inline std::pair::iterator, bool> +Multimap::Insert(const KTYPE &key, + const VTYPE &value) { using itr_traits = distributed_iterator_traits; size_t targetId = shad::hash{}(key) % rt::numLocalities(); @@ -410,7 +427,8 @@ Multimap::Insert(const KTYPE &key, const VTYPE &value auto &args(std::get<2>(args_)); auto mapPtr = HmapT::GetPtr(args.oid); auto lres = mapPtr->localMultimap_.Insert(args.key, args.value); - res_ptr->first = itr_traits::iterator_from_local (std::get<0>(args_), std::get<1>(args_), lres.first); + res_ptr->first = itr_traits::iterator_from_local( + std::get<0>(args_), std::get<1>(args_), lres.first); res_ptr->second = lres.second; }; rt::executeAtWithRet( @@ -440,16 +458,16 @@ inline void Multimap::AsyncInsert( } template -inline void Multimap::BufferedInsert(const KTYPE &key, const VTYPE &value) { +inline void Multimap::BufferedInsert( + const KTYPE &key, const VTYPE &value) { size_t targetId = shad::hash{}(key) % rt::numLocalities(); rt::Locality targetLocality(targetId); buffers_.Insert(EntryT(key, value), targetLocality); } template -inline void Multimap:: - BufferedAsyncInsert(rt::Handle &handle, const KTYPE &key, const VTYPE &value) { - +inline void Multimap::BufferedAsyncInsert( + rt::Handle &handle, const KTYPE &key, const VTYPE &value) { size_t targetId = shad::hash{}(key) % rt::numLocalities(); rt::Locality targetLocality(targetId); buffers_.AsyncInsert(handle, EntryT(key, value), targetLocality); @@ -473,7 +491,8 @@ inline void Multimap::Erase(const KTYPE &key) { } template -inline void Multimap::AsyncErase(rt::Handle &handle, const KTYPE &key) { +inline void Multimap::AsyncErase(rt::Handle &handle, + const KTYPE &key) { size_t targetId = shad::hash{}(key) % rt::numLocalities(); rt::Locality targetLocality(targetId); @@ -490,7 +509,8 @@ inline void Multimap::AsyncErase(rt::Handle &handle, } template -inline bool Multimap::Lookup(const KTYPE &key, LookupResult *res) { +inline bool Multimap::Lookup(const KTYPE &key, + LookupResult *res) { rt::Handle handle; AsyncLookup(handle, key, res); waitForCompletion(handle); @@ -499,78 +519,53 @@ inline bool Multimap::Lookup(const KTYPE &key, Lookup template inline void Multimap::AsyncLookup( - rt::Handle & handle, const KTYPE & key, LookupResult * result) { - + rt::Handle &handle, const KTYPE &key, LookupResult *result) { size_t targetId = shad::hash{}(key) % rt::numLocalities(); rt::Locality targetLocality(targetId); - + if (targetLocality == rt::thisLocality()) { localMultimap_.AsyncLookup(handle, key, result); - - } else { - auto lookupLambda = [](const LookupArgs & args, LookupRemoteResult * ret) { - auto my_key = args.key; - auto my_map = HmapT::GetPtr(args.oid); + } else { + auto lookupLambda = [](const LookupArgs &args, LookupRemoteResult *ret) { + auto my_key = args.key; + auto my_map = HmapT::GetPtr(args.oid); - LookupRemoteResult remote_result; - my_map->localMultimap_.LookupFromRemote(my_key, & remote_result); + LookupRemoteResult remote_result; + my_map->localMultimap_.LookupFromRemote(my_key, &remote_result); - * ret = remote_result; + *ret = remote_result; }; // executed at remote site, so meaning of remote and local are switched - auto lookupFetchLambda = [](rt::Handle & handle, const LookupRemoteResult & args) { - rt::dma(args.localLoc, args.local_elems, args.remote_elems, args.size); - free(args.remote_elems); + auto lookupFetchLambda = [](rt::Handle &handle, + const LookupRemoteResult &args) { + rt::dma(args.localLoc, args.local_elems, args.remote_elems, + args.size); + free(args.remote_elems); }; LookupArgs args = {oid_, key}; LookupRemoteResult remote_result; - rt::executeAtWithRet(targetLocality, lookupLambda, args, & remote_result); + rt::executeAtWithRet(targetLocality, lookupLambda, args, &remote_result); + + (*result).found = remote_result.found; + (*result).size = remote_result.size; - (* result).found = remote_result.found; - (* result).size = remote_result.size; - if (remote_result.found) { - (* result).value.resize(remote_result.size); - remote_result.localLoc = rt::thisLocality(); - remote_result.local_elems = (* result).value.data(); - rt::asyncExecuteAt(handle, targetLocality, lookupFetchLambda, remote_result); + (*result).value.resize(remote_result.size); + remote_result.localLoc = rt::thisLocality(); + remote_result.local_elems = (*result).value.data(); + rt::asyncExecuteAt(handle, targetLocality, lookupFetchLambda, + remote_result); } } } -template -inline void Multimap::readFromFiles( - rt::Handle & handle, std::string prefix, uint64_t lb, uint64_t ub) { - - auto readFileLambda = [](rt::Handle & handle, const RFArgs & args, size_t it) { - std::string line; - auto my_map = HmapT::GetPtr(args.oid); - std::string filename = args.prefix + std::to_string(args.lb + it); - printf("reading file %s\n", filename.c_str()); - - std::ifstream file(filename); - if (! file.is_open()) { printf("Cannot open file %s\n", filename.c_str()); exit(-1); } - - while (getline(file, line)) { - if (line[0] == '#') continue; // skip comments - - VTYPE record = VTYPE(line); - // my_map->AsyncInsert(handle, record.key(), record); - my_map->BufferedAsyncInsert(handle, record.key(), record); - } }; - - RFArgs args = {lb, oid_}; - memcpy(args.prefix, prefix.c_str(), prefix.size() + 1); - rt::asyncForEachOnAll(handle, readFileLambda, args, ub - lb + 1); -} - - template template -void Multimap::ForEachEntry(ApplyFunT &&function, Args &... args) { +void Multimap::ForEachEntry(ApplyFunT &&function, + Args &...args) { using FunctionTy = void (*)(const KTYPE &, VTYPE &, Args &...); FunctionTy fn = std::forward(function); @@ -581,7 +576,8 @@ void Multimap::ForEachEntry(ApplyFunT &&function, Arg feArgs arguments(oid_, fn, std::tuple(args...)); auto feLambda = [](const feArgs &args) { auto mapPtr = HmapT::GetPtr(std::get<0>(args)); - ArgsTuple argsTuple(&mapPtr->localMultimap_, std::get<1>(args), std::get<2>(args)); + ArgsTuple argsTuple(&mapPtr->localMultimap_, std::get<1>(args), + std::get<2>(args)); rt::forEachAt(rt::thisLocality(), LMapT::template ForEachEntryFunWrapper, argsTuple, mapPtr->localMultimap_.numBuckets_); @@ -592,8 +588,7 @@ void Multimap::ForEachEntry(ApplyFunT &&function, Arg template template void Multimap::AsyncForEachEntry( - rt::Handle &handle, ApplyFunT &&function, Args &... args) { - + rt::Handle &handle, ApplyFunT &&function, Args &...args) { using FunctionTy = void (*)(rt::Handle &, const KTYPE &, VTYPE &, Args &...); FunctionTy fn = std::forward(function); @@ -603,7 +598,8 @@ void Multimap::AsyncForEachEntry( feArgs arguments(oid_, fn, std::tuple(args...)); auto feLambda = [](rt::Handle &handle, const feArgs &args) { auto mapPtr = HmapT::GetPtr(std::get<0>(args)); - ArgsTuple argsTuple(&mapPtr->localMultimap_, std::get<1>(args), std::get<2>(args)); + ArgsTuple argsTuple(&mapPtr->localMultimap_, std::get<1>(args), + std::get<2>(args)); rt::asyncForEachAt( handle, rt::thisLocality(), @@ -615,7 +611,8 @@ void Multimap::AsyncForEachEntry( template template -void Multimap::ForEachKey(ApplyFunT &&function, Args &... args) { +void Multimap::ForEachKey(ApplyFunT &&function, + Args &...args) { using FunctionTy = void (*)(const KTYPE &, Args &...); FunctionTy fn = std::forward(function); @@ -625,7 +622,8 @@ void Multimap::ForEachKey(ApplyFunT &&function, Args feArgs arguments(oid_, fn, std::tuple(args...)); auto feLambda = [](const feArgs &args) { auto mapPtr = HmapT::GetPtr(std::get<0>(args)); - ArgsTuple argsTuple(&mapPtr->localMultimap_, std::get<1>(args), std::get<2>(args)); + ArgsTuple argsTuple(&mapPtr->localMultimap_, std::get<1>(args), + std::get<2>(args)); rt::forEachAt(rt::thisLocality(), LMapT::template ForEachKeyFunWrapper, argsTuple, mapPtr->localMultimap_.numBuckets_); @@ -635,8 +633,9 @@ void Multimap::ForEachKey(ApplyFunT &&function, Args template template -void Multimap::AsyncForEachKey( - rt::Handle &handle, ApplyFunT &&function, Args &... args) { +void Multimap::AsyncForEachKey(rt::Handle &handle, + ApplyFunT &&function, + Args &...args) { using FunctionTy = void (*)(rt::Handle &, const KTYPE &, Args &...); FunctionTy fn = std::forward(function); @@ -646,7 +645,8 @@ void Multimap::AsyncForEachKey( feArgs arguments(oid_, fn, std::tuple(args...)); auto feLambda = [](rt::Handle &handle, const feArgs &args) { auto mapPtr = HmapT::GetPtr(std::get<0>(args)); - ArgsTuple argsTuple(&mapPtr->localMultimap_, std::get<1>(args), std::get<2>(args)); + ArgsTuple argsTuple(&mapPtr->localMultimap_, std::get<1>(args), + std::get<2>(args)); rt::asyncForEachAt( handle, rt::thisLocality(), LMapT::template AsyncForEachKeyFunWrapper, @@ -657,7 +657,9 @@ void Multimap::AsyncForEachKey( template template -void Multimap::Apply(const KTYPE &key, ApplyFunT &&function, Args &... args) { +void Multimap::Apply(const KTYPE &key, + ApplyFunT &&function, + Args &...args) { size_t targetId = shad::hash{}(key) % rt::numLocalities(); rt::Locality targetLocality(targetId); @@ -668,11 +670,13 @@ void Multimap::Apply(const KTYPE &key, ApplyFunT &&fu using FunctionTy = void (*)(const KTYPE &, VTYPE &, Args &...); FunctionTy fn = std::forward(function); - using ArgsTuple = std::tuple>; + using ArgsTuple = + std::tuple>; ArgsTuple arguments(oid_, key, fn, std::tuple(args...)); auto feLambda = [](const ArgsTuple &args) { - constexpr auto Size = std::tuple_size(args))>::type>::value; + constexpr auto Size = std::tuple_size< + typename std::decay(args))>::type>::value; ArgsTuple &tuple = const_cast(args); LMapT *mapPtr = &(HmapT::GetPtr(std::get<0>(tuple))->localMultimap_); LMapT::CallApplyFun(mapPtr, std::get<1>(tuple), std::get<2>(tuple), @@ -684,8 +688,10 @@ void Multimap::Apply(const KTYPE &key, ApplyFunT &&fu template template -void Multimap::AsyncApply( - rt::Handle &handle, const KTYPE &key, ApplyFunT &&function, Args &... args) { +void Multimap::AsyncApply(rt::Handle &handle, + const KTYPE &key, + ApplyFunT &&function, + Args &...args) { size_t targetId = shad::hash{}(key) % rt::numLocalities(); rt::Locality targetLocality(targetId); @@ -693,13 +699,16 @@ void Multimap::AsyncApply( localMultimap_.AsyncApply(handle, key, function, args...); } else { - using FunctionTy = void (*)(rt::Handle &, const KTYPE &, VTYPE &, Args &...); + using FunctionTy = + void (*)(rt::Handle &, const KTYPE &, VTYPE &, Args &...); FunctionTy fn = std::forward(function); - using ArgsTuple = std::tuple>; + using ArgsTuple = + std::tuple>; ArgsTuple arguments(oid_, key, fn, std::tuple(args...)); auto feLambda = [](rt::Handle &handle, const ArgsTuple &args) { - constexpr auto Size = std::tuple_size(args))>::type>::value; + constexpr auto Size = std::tuple_size< + typename std::decay(args))>::type>::value; ArgsTuple &tuple(const_cast(args)); LMapT *mapPtr = &(HmapT::GetPtr(std::get<0>(tuple))->localMultimap_); LMapT::AsyncCallApplyFun(handle, mapPtr, std::get<1>(tuple), @@ -720,11 +729,13 @@ class multimap_iterator : public std::iterator { using value_type = NonConstT; multimap_iterator() {} - multimap_iterator(uint32_t locID, const OIDT mapOID, local_iterator_type &lit, T element) { + multimap_iterator(uint32_t locID, const OIDT mapOID, local_iterator_type &lit, + T element) { data_ = {locID, mapOID, lit, element}; } - multimap_iterator(uint32_t locID, const OIDT mapOID, local_iterator_type &lit) { + multimap_iterator(uint32_t locID, const OIDT mapOID, + local_iterator_type &lit) { auto mapPtr = MapT::GetPtr(mapOID); const LMap *lmapPtr = &(mapPtr->localMultimap_); @@ -740,7 +751,9 @@ class multimap_iterator : public std::iterator { if (static_cast(rt::thisLocality()) == 0) { auto localBegin = local_iterator_type::lmultimap_begin(lmapPtr); - if (localBegin != localEnd) { return multimap_iterator(0, mapPtr->oid_, localBegin); } + if (localBegin != localEnd) { + return multimap_iterator(0, mapPtr->oid_, localBegin); + } multimap_iterator beg(0, mapPtr->oid_, localEnd, T()); return ++beg; } @@ -764,7 +777,8 @@ class multimap_iterator : public std::iterator { } static multimap_iterator multimap_end(const MapT *mapPtr) { - local_iterator_type lend = local_iterator_type::lmultimap_end(&(mapPtr->localMultimap_)); + local_iterator_type lend = + local_iterator_type::lmultimap_end(&(mapPtr->localMultimap_)); multimap_iterator end(rt::numLocalities(), OIDT(0), lend, T()); return end; } @@ -773,7 +787,9 @@ class multimap_iterator : public std::iterator { return (data_ == other.data_); } - bool operator!=(const multimap_iterator &other) const { return !(*this == other); } + bool operator!=(const multimap_iterator &other) const { + return !(*this == other); + } T operator*() const { return data_.element_; } @@ -783,19 +799,25 @@ class multimap_iterator : public std::iterator { if (static_cast(rt::thisLocality()) == data_.locId_) { const LMap *lmapPtr = &(mapPtr->localMultimap_); auto lend = local_iterator_type::lmultimap_end(lmapPtr); - if (data_.lmapIt_ != lend) { ++(data_.lmapIt_); } + if (data_.lmapIt_ != lend) { + ++(data_.lmapIt_); + } if (data_.lmapIt_ != lend) { - data_.element_ = *(data_.lmapIt_); - return *this; + data_.element_ = *(data_.lmapIt_); + return *this; - } else { // find the local begin on next localities + } else { // find the local begin on next localities itData itd; for (uint32_t i = data_.locId_ + 1; i < rt::numLocalities(); ++i) { - rt::executeAtWithRet(rt::Locality(i), getLocBeginIt, data_.oid_, &itd); + rt::executeAtWithRet(rt::Locality(i), getLocBeginIt, data_.oid_, + &itd); // if Data is valid - if (itd.locId_ != rt::numLocalities()) { data_ = itd; return *this; } + if (itd.locId_ != rt::numLocalities()) { + data_ = itd; + return *this; + } } data_ = itData(rt::numLocalities(), OIDT(0), lend, T()); @@ -827,7 +849,8 @@ class multimap_iterator : public std::iterator { local_iterator_type end_; }; - static local_iterator_range local_range(multimap_iterator &B, multimap_iterator &E) { + static local_iterator_range local_range(multimap_iterator &B, + multimap_iterator &E) { auto mapPtr = MapT::GetPtr(B.data_.oid_); local_iterator_type lbeg, lend; uint32_t thisLocId = static_cast(rt::thisLocality()); @@ -847,18 +870,26 @@ class multimap_iterator : public std::iterator { return local_iterator_range(lbeg, lend); } - static rt::localities_range localities(multimap_iterator &B, multimap_iterator &E) { + static rt::localities_range localities(multimap_iterator &B, + multimap_iterator &E) { return rt::localities_range(rt::Locality(B.data_.locId_), - rt::Locality(std::min(rt::numLocalities(), E.data_.locId_ + 1))); + rt::Locality(std::min( + rt::numLocalities(), E.data_.locId_ + 1))); } - static multimap_iterator iterator_from_local(multimap_iterator &B, multimap_iterator &E, local_iterator_type itr) { - return multimap_iterator(static_cast(rt::thisLocality()), B.data_.oid_, itr); + static multimap_iterator iterator_from_local(multimap_iterator &B, + multimap_iterator &E, + local_iterator_type itr) { + return multimap_iterator(static_cast(rt::thisLocality()), + B.data_.oid_, itr); } private: struct itData { - itData() : oid_(0), lmapIt_(nullptr, 0, 0, nullptr, nullptr, typename std::vector::iterator()) {} + itData() + : oid_(0), + lmapIt_(nullptr, 0, 0, nullptr, nullptr, + typename std::vector::iterator()) {} itData(uint32_t locId, OIDT oid, local_iterator_type lmapIt, T element) : locId_(locId), oid_(oid), lmapIt_(lmapIt), element_(element) {} @@ -881,7 +912,8 @@ class multimap_iterator : public std::iterator { auto localEnd = local_iterator_type::lmultimap_end(lmapPtr); auto localBegin = local_iterator_type::lmultimap_begin(lmapPtr); if (localBegin != localEnd) { - *res = itData(static_cast(rt::thisLocality()), mapOID, localBegin, *localBegin); + *res = itData(static_cast(rt::thisLocality()), mapOID, + localBegin, *localBegin); } else { *res = itData(rt::numLocalities(), OIDT(0), localEnd, T()); } @@ -895,14 +927,18 @@ class multimap_iterator : public std::iterator { ++cit; if (cit != localEnd) { - *res = itData(static_cast(rt::thisLocality()), itd.oid_, cit, *cit); + *res = itData(static_cast(rt::thisLocality()), itd.oid_, cit, + *cit); return; } else { itData outitd; for (uint32_t i = itd.locId_ + 1; i < rt::numLocalities(); ++i) { rt::executeAtWithRet(rt::Locality(i), getLocBeginIt, itd.oid_, &outitd); // It Data is valid - if (outitd.locId_ != rt::numLocalities()) { *res = outitd; return; } + if (outitd.locId_ != rt::numLocalities()) { + *res = outitd; + return; + } } *res = itData(rt::numLocalities(), OIDT(0), localEnd, T()); }