ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/gclib/gclib/threads.cpp
Revision: 310
Committed: Fri Mar 22 20:06:27 2013 UTC (6 years, 1 month ago) by gpertea
File size: 7043 byte(s)
Log Message:
sync with igm repo

Line File contents
1 #include <iostream>
2 #include <list>
3 #include "GThreads.h"
4
5
6 using namespace std;
7 //using namespace tthread;
8
9 // Thread local storage variable (not available on Mac OSX ?!)
10 #ifndef GTHREADS_NO_TLS
11 thread_local int gLocalVar;
12 #endif
13
14 // Mutex + global count variable
15 GMutex gMutex;
16 GFastMutex gFastMutex;
17 int gCount;
18
19 // Condition variable
20 GConditionVar gCond;
21
22 // Thread function: Thread ID
23 void ThreadIDs(GThreadData& my)
24 {
25 {
26 GLockGuard<GMutex> lock(gMutex);
27
28 //cout << " My thread id is " << thisThread->get_id() << "." << endl << flush;
29 cout << " My thread id is " << my.thread->get_id() << "." << endl << flush;
30 }
31 this_thread::sleep_for(chrono::seconds(4));
32 }
33
34 #ifndef GTHREADS_NO_TLS
35 // Thread function: Thread-local storage
36 void ThreadTLS(void * aArg)
37 {
38 gLocalVar = 2;
39 cout << " My gLocalVar is " << gLocalVar << "." << endl;
40 }
41 #endif
42
43 // Thread function: Mutex locking
44 void ThreadLock(void * aArg)
45 {
46 for(int i = 0; i < 10000; ++ i)
47 {
48 GLockGuard<GMutex> lock(gMutex);
49 ++ gCount;
50 }
51 }
52
53 // Thread function: Mutex locking
54 void ThreadLock2(void * aArg)
55 {
56 for(int i = 0; i < 10000; ++ i)
57 {
58 GLockGuard<GFastMutex> lock(gFastMutex);
59 ++ gCount;
60 }
61 }
62
63 // Thread function: Condition notifier
64 void ThreadCondition1(void * aArg)
65 {
66 GLockGuard<GMutex> lock(gMutex);
67 -- gCount;
68 gCond.notify_all();
69 }
70
71 // Thread function: Condition waiter
72 void ThreadCondition2(void * aArg)
73 {
74 cout << " Wating:" << flush;
75 GLockGuard<GMutex> lock(gMutex);
76 while(gCount > 0)
77 {
78 cout << "*" << gCount << flush;
79 gCond.wait(gMutex);
80 cout << "received notification at " << gCount << endl << flush;
81 }
82 cout << "-reached 0!" << endl;
83 }
84
85 // Thread function: Yield
86 void ThreadYield(void * aArg)
87 {
88 // Yield...
89 this_thread::yield();
90 }
91
92
93 // This is the main program (i.e. the main thread)
94 int main()
95 {
96 // Test 1: Show number of CPU cores in the system
97 cout << "PART I: Info" << endl;
98 cout << " Number of processor cores: " << GThread::hardware_concurrency() << endl;
99
100 // Test 2: thread IDs
101 /*
102 cout << endl << "PART II: Thread IDs" << endl;
103 {
104 // Show the main thread ID
105 //cout << " Main thread id is " << this_thread::get_id() << "." << endl;
106
107 // Start a bunch of child threads - only run a single thread at a time
108 GThread t1(ThreadIDs, 0);
109 this_thread::sleep_for(chrono::milliseconds(400));
110 GThread t2(ThreadIDs, 0);
111 this_thread::sleep_for(chrono::milliseconds(400));
112 GThread t3(ThreadIDs, 0);
113 this_thread::sleep_for(chrono::milliseconds(400));
114 GThread t4(ThreadIDs, 0);
115 //t1.join();
116 //t2.join();
117 //t3.join();
118 //t4.join();
119 this_thread::sleep_for(chrono::milliseconds(200));
120 cout << "Waiting for all threads to finish.." << flush;
121 int num_threads;
122 while ((num_threads=GThread::num_running())>0) {
123 cout << "." << num_threads << "." << flush;
124 this_thread::sleep_for(chrono::milliseconds(300));
125 }
126 cout << ".. Done. " << endl;
127 }
128
129 // Test 3: thread local storage
130 cout << endl << "PART III: Thread local storage" << endl;
131 #ifndef GTHREADS_NO_TLS
132 {
133 // Clear the TLS variable (it should keep this value after all threads are
134 // finished).
135 gLocalVar = 1;
136 cout << " Main gLocalVar is " << gLocalVar << "." << endl;
137
138 // Start a child thread that modifies gLocalVar
139 GThread t1(ThreadTLS, 0);
140 t1.join();
141
142 // Check if the TLS variable has changed
143 if(gLocalVar == 1)
144 cout << " Main gLocalVar was not changed by the child thread - OK!" << endl;
145 else
146 cout << " Main gLocalVar was changed by the child thread - FAIL!" << endl;
147 }
148 #else
149 cout << " TLS is not supported on this platform..." << endl;
150 #endif
151
152 // Test 4: mutex locking
153 cout << endl << "PART IV: Mutex locking (100 threads x 10000 iterations)" << endl;
154 {
155 // Clear the global counter.
156 gCount = 0;
157
158 // Start a bunch of child threads
159 list<GThread *> threadList;
160 for(int i = 0; i < 100; ++ i)
161 threadList.push_back(new GThread(ThreadLock, 0));
162
163 // Wait for the threads to finish
164 list<GThread *>::iterator it;
165 for(it = threadList.begin(); it != threadList.end(); ++ it)
166 {
167 GThread * t = *it;
168 t->join();
169 delete t;
170 }
171
172 // Check the global count
173 cout << " gCount = " << gCount << endl;
174 }
175
176 // Test 5: fast_mutex locking
177 cout << endl << "PART V: Fast mutex locking (100 threads x 10000 iterations)" << endl;
178 {
179 // Clear the global counter.
180 gCount = 0;
181
182 // Start a bunch of child threads
183 list<GThread *> threadList;
184 for(int i = 0; i < 100; ++ i)
185 threadList.push_back(new GThread(ThreadLock2, 0));
186
187 // Wait for the threads to finish
188 list<GThread *>::iterator it;
189 for(it = threadList.begin(); it != threadList.end(); ++ it)
190 {
191 GThread * t = *it;
192 t->join();
193 delete t;
194 }
195
196 // Check the global count
197 cout << " gCount = " << gCount << endl;
198 }
199 */
200 // Test 6: condition variable
201 cout << endl << "PART VI: Condition variable (40 + 1 threads)" << endl;
202 {
203 // Set the global counter to the number of threads to run.
204 {
205 GLockGuard<GMutex> lock(gMutex);
206 gCount = 6;
207 }
208
209 // Start the waiting thread (it will wait for gCount to reach zero).
210 GThread t1(ThreadCondition2, 0);
211
212 this_thread::sleep_for(chrono::milliseconds(400));
213 {
214
215 for (int c=5;c>=0;c--) {
216 {
217 GLockGuard<GMutex> lock(gMutex);
218 --gCount;
219 gCond.notify_one();
220 }
221 cout << "Notify_" << c << "|" << flush;
222 //this_thread::sleep_for(chrono::milliseconds(200));
223 cout << "Notify_sent" << c << "|" << flush;
224 }
225 }
226
227 // Start a bunch of child threads (these will decrease gCount by 1 when they
228 // finish)
229 /*
230 list<GThread *> threadList;
231 for(int i = 0; i < 40; ++ i)
232 threadList.push_back(new GThread(ThreadCondition1, 0));
233 */
234 // Wait for the waiting thread to finish
235 t1.join();
236
237 // Wait for the other threads to finish
238 /*
239 list<GThread *>::iterator it;
240 for(it = threadList.begin(); it != threadList.end(); ++ it)
241 {
242 GThread * t = *it;
243 t->join();
244 delete t;
245 }
246 */
247 }
248 /*
249 // Test 7: yield
250 cout << endl << "PART VII: Yield (40 + 1 threads)" << endl;
251 {
252 // Start a bunch of child threads
253 list<GThread *> threadList;
254 for(int i = 0; i < 40; ++ i)
255 threadList.push_back(new GThread(ThreadYield, 0));
256
257 // Yield...
258 this_thread::yield();
259
260 // Wait for the threads to finish
261 list<GThread *>::iterator it;
262 for(it = threadList.begin(); it != threadList.end(); ++ it)
263 {
264 GThread * t = *it;
265 t->join();
266 delete t;
267 }
268 }
269
270 // Test 8: sleep
271 cout << endl << "PART VIII: Sleep (10 x 100 ms)" << endl;
272 {
273 // Sleep...
274 cout << " Sleeping" << flush;
275 for(int i = 0; i < 10; ++ i)
276 {
277 this_thread::sleep_for(chrono::milliseconds(100));
278 cout << "." << flush;
279 }
280 cout << endl;
281 }
282 */
283 }