eikhner

ConcurrentMap_brown_belt

Aug 27th, 2019
42
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #include <future>
  2. #include <mutex>
  3. #include <unordered_map>
  4. #include <vector>
  5. #include <utility>
  6. #include <algorithm>
  7. #include <random>
  8. #include <thread>
  9. #include <shared_mutex>
  10.  
  11. using namespace std;
  12.  
  13. template<typename K, typename V, typename Hash = std::hash<K>>
  14. class ConcurrentMap {
  15.     struct Key {
  16.         K data;
  17.         size_t hash;
  18.  
  19.         explicit Key(K data) : data(std::move(data)), hash(Hash()(this->data)) {}
  20.  
  21.         bool operator==(const Key &other) const {
  22.             return data == other.data;
  23.         }
  24.     };
  25.  
  26.     struct KeyHasher {
  27.         auto operator()(const Key &value) const {
  28.             return value.hash;
  29.         }
  30.     };
  31.  
  32.     using InnerMapType = std::unordered_map<Key, V, KeyHasher>;
  33.  
  34.     struct SharedMap {
  35.         mutable std::shared_mutex mtx;
  36.         InnerMapType map;
  37.     };
  38.  
  39. public:
  40.     using MapType = std::unordered_map<K, V, Hash>;
  41.  
  42.     class WriteAccess {
  43.         std::lock_guard<std::shared_mutex> guard;
  44.     public:
  45.         V &ref_to_value;
  46.  
  47.         WriteAccess(InnerMapType &map, Key &key, std::shared_mutex &mtx) : guard(mtx),
  48.                                                                            ref_to_value(map[std::move(key)]) {};
  49.     };
  50.  
  51.     class ReadAccess {
  52.         std::shared_lock<std::shared_mutex> lock;
  53.     public:
  54.         const V &ref_to_value;
  55.  
  56.         ReadAccess(const InnerMapType &map, const Key &key, std::shared_mutex &mtx) : lock(mtx),
  57.                                                                                       ref_to_value(map.at(key)) {};
  58.     };
  59.  
  60.     explicit ConcurrentMap(size_t bucket_count) : data(bucket_count) {}
  61.  
  62.     WriteAccess operator[](const K &key) {
  63.         Key map_key(key);
  64.         auto &[mtx, map] = data[map_key.hash % data.size()];
  65.         return {map, map_key, mtx};
  66.     }
  67.  
  68.     ReadAccess At(const K &key) const {
  69.         const Key map_key(key);
  70.         auto &[mtx, map] = data[map_key.hash % data.size()];
  71.         return {map, map_key, mtx};
  72.     }
  73.  
  74.     bool Has(const K &key) const {
  75.         const Key map_key(key);
  76.         auto &[mtx, map] = data[map_key.hash % data.size()];
  77.         std::shared_lock locker(mtx);
  78.         return map.find(map_key) != map.end();
  79.     }
  80.  
  81.     MapType BuildOrdinaryMap() const {
  82.         MapType to_ret;
  83.         for (auto &[mtx, map] : data) {
  84.             std::shared_lock locker(mtx);
  85.             for (auto &[key, val] : map) {
  86.                 to_ret[key.data] = val;
  87.             }
  88.         }
  89.         return to_ret;
  90.     }
  91.  
  92. private:
  93.     std::vector<SharedMap> data;
  94. };
Add Comment
Please, Sign In to add comment