-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy paththreadSamples-part1.cpp
More file actions
138 lines (134 loc) · 3.52 KB
/
threadSamples-part1.cpp
File metadata and controls
138 lines (134 loc) · 3.52 KB
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include <thread>
#include <iostream>
#include <functional>
using namespace std;
template <typename T>
class MutexSafe
{
private:
mutex _mutex;
T* _resource;
T* operator ->(){}
T& operator &(){}
public:
MutexSafe(T* resource):_resource(resource){}
~MutexSafe(){delete _resource;}
void lock()
{
_mutex.lock();
}
void unlock()
{
_mutex.unlock();
}
bool try_lock()
{
return _mutex.try_lock();
}
mutex& Mutex()
{
return _mutex;
}
//this is version 3 of Acquire
// it requires the passed in lock parameter is the safe object itself
//thus it avoids the issue that an arbitrary lock can access the resource.
//Also, it now requires the lock to be the same type of Safe that Acquire is.
T& Acquire (unique_lock<MutexSafe<T>>& lock)
{
MutexSafe<T> *_safe = lock.mutex();
if(&_safe->Mutex()!=&_mutex)
{
throw "wrong lock object passed to Acquire function.\n";
}
return *_resource;
}
//This overloaded Acquire allows unique_lock<mutex> to be passed in as a parameter
T& Acquire (unique_lock<mutex>& lock)
{
if(lock.mutex()!=&_mutex)
{
throw "wrong lock object passed to Acquire function.\n";
}
return *_resource;
}
};
void DannyWrite(string &blackboard)
{
blackboard=+"My";
this_thread::sleep_for(std::chrono::milliseconds(rand()%3));
blackboard+= " name";
this_thread::sleep_for(std::chrono::milliseconds(rand()%3));
blackboard+=" is";
this_thread::sleep_for(std::chrono::milliseconds(rand()%3));
blackboard+= " Danny\n";
}
void PeterWrite(string& blackboard)
{
blackboard+="My";
this_thread::sleep_for(std::chrono::milliseconds(rand()%3));
blackboard+= " name";
this_thread::sleep_for(std::chrono::milliseconds(rand()%3));
blackboard+=" is";
this_thread::sleep_for(std::chrono::milliseconds(rand()%3));
blackboard+= " Peter\n";
}
void DemoResouceConflict()
{
string blackboard;
thread DannyThread(DannyWrite, std::ref(blackboard));
thread PeterThread(PeterWrite,std::ref(blackboard));
DannyThread.join();
PeterThread.join();
cout<<blackboard<<endl;
}
typedef MutexSafe<string> Safe;
void SafeDannyWrite(Safe& safe)
{
unique_lock<Safe> lock(safe);
string& blackboard = safe.Acquire(lock);
DannyWrite(blackboard);
}
void SafePeterWrite(Safe& safe)
{
unique_lock<Safe> lock(safe);
string& blackboard = safe.Acquire(lock);
PeterWrite(blackboard);
}
void TestSafeSmartlock()
{
Safe safe(new string());
thread DannyThread(SafeDannyWrite,ref(safe));
thread PeterThread(SafePeterWrite, ref(safe));
DannyThread.join();
PeterThread.join();
unique_lock<Safe> lock(safe);
string& blackboard = safe.Acquire(lock);
cout<<blackboard<<endl;
}
void PeterWriteWithMutex(mutex& amutex, string& blackboard )
{
unique_lock<std::mutex> lk(amutex);
PeterWrite(blackboard);
}
void DannywriteWithMutex(mutex& amutex, string& blackboard)
{
unique_lock<std::mutex> lk(amutex);
DannyWrite(blackboard);
}
void TestNomalSafeLock()
{
string blackboard;
std::mutex amutex;
thread DannyThread(DannywriteWithMutex, std::ref(amutex), std::ref(blackboard));
thread PeterThread(PeterWriteWithMutex,std::ref(amutex), std::ref(blackboard));
DannyThread.join();
PeterThread.join();
cout<<blackboard<<endl;
}
int main()
{
//DemoResouceConflict();
TestSafeSmartlock();
//TestNomalSafeLock();
return 0;
}