ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/gclib/gclib/threads.cpp
Revision: 156
Committed: Fri Jan 27 18:29:55 2012 UTC (7 years, 4 months ago) by gpertea
File size: 6690 byte(s)
Log Message:
adding refactored TinyThread++ code

Line User Rev File contents
1 gpertea 156 #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     }