forked from Expensify/Bedrock
-
Notifications
You must be signed in to change notification settings - Fork 0
/
SynchronizedMap.h
69 lines (65 loc) · 1.93 KB
/
SynchronizedMap.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
// This is a class that's just a std::map that's thread-safe. It does not implement every std::map function, please add
// them as needed.
#pragma once
template <typename T, typename U>
class SynchronizedMap {
public:
// A LockGuard is like a std::lock_guard, but for the entire object. It allows the whole thing to be locked so
// that the caller can perform multiple operations atomically. A LockGuard can easily be created for a
// SynchronizedMap by calling `scopedLock()` on the map.
friend class LockGuard;
class LockGuard {
public:
LockGuard(SynchronizedMap& map) : _map(map) {
_map._m.lock();
}
~LockGuard() {
_map._m.unlock();
}
private:
SynchronizedMap& _map;
};
// These are just passed through to the underlying object, but with the lock locked first.
auto begin() {
lock_guard <decltype(_m)> lock(_m);
return _data.begin();
}
auto clear() {
lock_guard <decltype(_m)> lock(_m);
return _data.clear();
}
// Note: Key is copied, value is moved.
template <typename V, typename W>
auto emplace(V& key, W&& value) {
lock_guard <decltype(_m)> lock(_m);
return _data.emplace(key, move(value));
}
auto empty() {
lock_guard <decltype(_m)> lock(_m);
return _data.empty();
}
auto end() {
lock_guard <decltype(_m)> lock(_m);
return _data.end();
}
template <typename V>
auto erase(V item) {
lock_guard <decltype(_m)> lock(_m);
return _data.erase(item);
}
template <typename V>
auto find(V item) {
lock_guard <decltype(_m)> lock(_m);
return _data.find(item);
}
auto size() {
lock_guard <decltype(_m)> lock(_m);
return _data.size();
}
LockGuard scopedLock() {
return LockGuard(*this);
}
private :
map<T, U> _data;
recursive_mutex _m;
};