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