-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathconcurrent_map.h
70 lines (52 loc) · 1.53 KB
/
concurrent_map.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#pragma once
#include <atomic>
#include <map>
#include <mutex>
#include <vector>
using namespace std::string_literals;
template <typename Key, typename Value>
class ConcurrentMap {
public:
static_assert(std::is_integral_v<Key>, "ConcurrentMap supports only integer keys"s);
struct Access {
Access(Value& value, std::mutex& m)
: ref_to_value(value)
, m_outer(m) {
}
Value& ref_to_value;
std::mutex& m_outer;
~Access() {
m_outer.unlock();
}
};
explicit ConcurrentMap(size_t bucket_count)
: bucket_count_(bucket_count)
, mutexes_(bucket_count) {
if (bucket_count_ == 0u) {
throw std::invalid_argument("Invalid bucket_count"s);
}
super_map_.resize(bucket_count);
};
Access operator[](const Key& key) {
std::atomic<uint64_t> map_number = static_cast<uint64_t>(key) % bucket_count_;
mutexes_[map_number].lock();
auto& link = super_map_[map_number][key];
return { link, mutexes_[map_number] };
}
std::map<Key, Value> BuildOrdinaryMap() {
std::map<Key, Value> result;
std::atomic_int count = 0;
for (auto& it : super_map_) {
mutexes_[count].lock();
result.merge(it);
mutexes_[count].unlock();
++count;
}
return result;
}
private:
std::vector<std::map<Key, Value>> super_map_;
size_t bucket_count_;
Value value_;
std::vector<std::mutex> mutexes_;
};