-
Notifications
You must be signed in to change notification settings - Fork 1
/
ThreadSafeSet.h
118 lines (103 loc) · 3.62 KB
/
ThreadSafeSet.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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#ifndef THREADSAFESET_H
#define THREADSAFESET_H
#include <mutex>
#include <thread>
#include <unordered_set>
/**
* A wrapper class for std::set. This wrapper provides several thread-safe operations by using a mutex.
*/
template <class C>
class ThreadSafeSet {
public:
/**
* Default constructor.
*
* Initializes sleepLockMilliseconds, the number of miliseconds a thread should sleep after encountering a conflict
*
* @tparam C the type of data the set stores.
*/
ThreadSafeSet();
/**
* Constructor.
*
* Initializes sleepLockMilliseconds, the number of miliseconds a thread should sleep after encountering a conflict.
* If the parameter passed is equal or less 0, sleepLockMiliseconds defaults to 1.
*
* @tparam C the type of data the set stores.
* @param sLockMiliseconds the number of miliseconds a thread should sleep after encountering a conflict
*/
ThreadSafeSet(int sLockMilliseconds);
/**
* Thread safe wrapper around unordered_set.contains().
*
* @tparam C the type of data the set stores.
* @param data the object to search for.
* @return true if the set contains the object, false otherwise.
*/
bool contains(C data);
/**
* Thread safe wrapper around unordered_set.insert().
*
* @tparam C the type of data the set stores.
* @param data the object to insert.
* @return true if the set contains the object, false otherwise.
*/
bool safeInsert(C data);
/**
* Thread safe wrapper around set's copy constructor.
*
* @tparam C the type of data the set stores.
* @return a reference to the local variable.
*/
ThreadSafeSet& operator=(const ThreadSafeSet& copy);
private:
std::mutex mu;
std::unordered_set<C> set;
std::chrono::milliseconds sleepLockMilliseconds;
};
template<class C>
inline ThreadSafeSet<C>::ThreadSafeSet() {
sleepLockMilliseconds = std::chrono::milliseconds(1);
}
template<class C>
inline ThreadSafeSet<C>::ThreadSafeSet(int sLockMilliseconds) {
if(sLockMilliseconds > 0)
sleepLockMilliseconds = std::chrono::milliseconds(sLockMilliseconds);
else
sleepLockMilliseconds = std::chrono::milliseconds(1);
}
template<class C>
inline bool ThreadSafeSet<C>::contains(C data) {
std::unique_lock<std::mutex> lock(mu, std::try_to_lock);
while(!lock.owns_lock()) {
std::this_thread::sleep_for(sleepLockMilliseconds);
lock.try_lock();
}
// If the set iterator is not equal to the end of the set, the set contains the data.
bool temp = !(set.find(data) == set.end());
return temp;
}
template<class C>
inline bool ThreadSafeSet<C>::safeInsert(C data) {
std::unique_lock<std::mutex> lock(mu, std::try_to_lock);
while(!lock.owns_lock()) {
std::this_thread::sleep_for(sleepLockMilliseconds);
lock.try_lock();
}
bool temp = set.insert(data).second;
return temp;
}
template<class C>
inline ThreadSafeSet<C>& ThreadSafeSet<C>::operator=(const ThreadSafeSet<C>& copy) {
std::unique_lock<std::mutex> lock(mu, std::try_to_lock);
while(!lock.owns_lock()) {
std::this_thread::sleep_for(sleepLockMilliseconds);
lock.try_lock();
}
set.clear();
for(C element : copy.set) {
set.insert(element);
}
return *this;
}
#endif