View difference between Paste ID: AwTJ8nkg and 8JBhkA5T
SHOW: | | - or go back to the newest paste.
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
};