cannam@62
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
cannam@62
|
2
|
cannam@62
|
3 /*
|
cannam@62
|
4 QM DSP Library
|
cannam@62
|
5
|
cannam@62
|
6 Centre for Digital Music, Queen Mary, University of London.
|
cannam@62
|
7 This file copyright Chris Cannam, used with permission.
|
cannam@62
|
8 */
|
cannam@62
|
9
|
cannam@62
|
10 #include "Thread.h"
|
cannam@62
|
11
|
cannam@62
|
12 #include <iostream>
|
cannam@62
|
13 #include <cstdlib>
|
cannam@62
|
14
|
cannam@62
|
15 #ifdef USE_PTHREADS
|
cannam@62
|
16 #include <sys/time.h>
|
cannam@62
|
17 #include <time.h>
|
cannam@62
|
18 #endif
|
cannam@62
|
19
|
cannam@62
|
20 using std::cerr;
|
cannam@62
|
21 using std::endl;
|
cannam@62
|
22 using std::string;
|
cannam@62
|
23
|
cannam@62
|
24 #ifdef _WIN32
|
cannam@62
|
25
|
cannam@62
|
26 Thread::Thread() :
|
cannam@62
|
27 m_id(0),
|
cannam@62
|
28 m_extant(false)
|
cannam@62
|
29 {
|
cannam@62
|
30 #ifdef DEBUG_THREAD
|
cannam@62
|
31 cerr << "THREAD DEBUG: Created thread object " << this << endl;
|
cannam@62
|
32 #endif
|
cannam@62
|
33 }
|
cannam@62
|
34
|
cannam@62
|
35 Thread::~Thread()
|
cannam@62
|
36 {
|
cannam@62
|
37 #ifdef DEBUG_THREAD
|
cannam@62
|
38 cerr << "THREAD DEBUG: Destroying thread object " << this << ", id " << m_id << endl;
|
cannam@62
|
39 #endif
|
cannam@62
|
40 if (m_extant) {
|
cannam@62
|
41 WaitForSingleObject(m_id, INFINITE);
|
cannam@62
|
42 }
|
cannam@62
|
43 #ifdef DEBUG_THREAD
|
cannam@62
|
44 cerr << "THREAD DEBUG: Destroyed thread object " << this << endl;
|
cannam@62
|
45 #endif
|
cannam@62
|
46 }
|
cannam@62
|
47
|
cannam@62
|
48 void
|
cannam@62
|
49 Thread::start()
|
cannam@62
|
50 {
|
cannam@62
|
51 m_id = CreateThread(NULL, 0, staticRun, this, 0, 0);
|
cannam@62
|
52 if (!m_id) {
|
cannam@62
|
53 cerr << "ERROR: thread creation failed" << endl;
|
cannam@62
|
54 exit(1);
|
cannam@62
|
55 } else {
|
cannam@62
|
56 #ifdef DEBUG_THREAD
|
cannam@62
|
57 cerr << "THREAD DEBUG: Created thread " << m_id << " for thread object " << this << endl;
|
cannam@62
|
58 #endif
|
cannam@62
|
59 m_extant = true;
|
cannam@62
|
60 }
|
cannam@62
|
61 }
|
cannam@62
|
62
|
cannam@62
|
63 void
|
cannam@62
|
64 Thread::wait()
|
cannam@62
|
65 {
|
cannam@62
|
66 if (m_extant) {
|
cannam@62
|
67 #ifdef DEBUG_THREAD
|
cannam@62
|
68 cerr << "THREAD DEBUG: Waiting on thread " << m_id << " for thread object " << this << endl;
|
cannam@62
|
69 #endif
|
cannam@62
|
70 WaitForSingleObject(m_id, INFINITE);
|
cannam@62
|
71 #ifdef DEBUG_THREAD
|
cannam@62
|
72 cerr << "THREAD DEBUG: Waited on thread " << m_id << " for thread object " << this << endl;
|
cannam@62
|
73 #endif
|
cannam@62
|
74 m_extant = false;
|
cannam@62
|
75 }
|
cannam@62
|
76 }
|
cannam@62
|
77
|
cannam@62
|
78 Thread::Id
|
cannam@62
|
79 Thread::id()
|
cannam@62
|
80 {
|
cannam@62
|
81 return m_id;
|
cannam@62
|
82 }
|
cannam@62
|
83
|
cannam@62
|
84 bool
|
cannam@62
|
85 Thread::threadingAvailable()
|
cannam@62
|
86 {
|
cannam@62
|
87 return true;
|
cannam@62
|
88 }
|
cannam@62
|
89
|
cannam@62
|
90 DWORD
|
cannam@62
|
91 Thread::staticRun(LPVOID arg)
|
cannam@62
|
92 {
|
cannam@62
|
93 Thread *thread = static_cast<Thread *>(arg);
|
cannam@62
|
94 #ifdef DEBUG_THREAD
|
cannam@62
|
95 cerr << "THREAD DEBUG: " << (void *)GetCurrentThreadId() << ": Running thread " << thread->m_id << " for thread object " << thread << endl;
|
cannam@62
|
96 #endif
|
cannam@62
|
97 thread->run();
|
cannam@62
|
98 return 0;
|
cannam@62
|
99 }
|
cannam@62
|
100
|
cannam@62
|
101 Mutex::Mutex()
|
cannam@62
|
102 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
103 :
|
cannam@62
|
104 m_lockedBy(-1)
|
cannam@62
|
105 #endif
|
cannam@62
|
106 {
|
cannam@62
|
107 m_mutex = CreateMutex(NULL, FALSE, NULL);
|
cannam@62
|
108 #ifdef DEBUG_MUTEX
|
cannam@62
|
109 cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised mutex " << &m_mutex << endl;
|
cannam@62
|
110 #endif
|
cannam@62
|
111 }
|
cannam@62
|
112
|
cannam@62
|
113 Mutex::~Mutex()
|
cannam@62
|
114 {
|
cannam@62
|
115 #ifdef DEBUG_MUTEX
|
cannam@62
|
116 cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying mutex " << &m_mutex << endl;
|
cannam@62
|
117 #endif
|
cannam@62
|
118 CloseHandle(m_mutex);
|
cannam@62
|
119 }
|
cannam@62
|
120
|
cannam@62
|
121 void
|
cannam@62
|
122 Mutex::lock()
|
cannam@62
|
123 {
|
cannam@62
|
124 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
125 DWORD tid = GetCurrentThreadId();
|
cannam@62
|
126 if (m_lockedBy == tid) {
|
cannam@62
|
127 cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl;
|
cannam@62
|
128 }
|
cannam@62
|
129 #endif
|
cannam@62
|
130 #ifdef DEBUG_MUTEX
|
cannam@62
|
131 cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl;
|
cannam@62
|
132 #endif
|
cannam@62
|
133 WaitForSingleObject(m_mutex, INFINITE);
|
cannam@62
|
134 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
135 m_lockedBy = tid;
|
cannam@62
|
136 #endif
|
cannam@62
|
137 #ifdef DEBUG_MUTEX
|
cannam@62
|
138 cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl;
|
cannam@62
|
139 #endif
|
cannam@62
|
140 }
|
cannam@62
|
141
|
cannam@62
|
142 void
|
cannam@62
|
143 Mutex::unlock()
|
cannam@62
|
144 {
|
cannam@62
|
145 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
146 DWORD tid = GetCurrentThreadId();
|
cannam@62
|
147 if (m_lockedBy != tid) {
|
cannam@62
|
148 cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl;
|
cannam@62
|
149 return;
|
cannam@62
|
150 }
|
cannam@62
|
151 #endif
|
cannam@62
|
152 #ifdef DEBUG_MUTEX
|
cannam@62
|
153 cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl;
|
cannam@62
|
154 #endif
|
cannam@62
|
155 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
156 m_lockedBy = -1;
|
cannam@62
|
157 #endif
|
cannam@62
|
158 ReleaseMutex(m_mutex);
|
cannam@62
|
159 }
|
cannam@62
|
160
|
cannam@62
|
161 bool
|
cannam@62
|
162 Mutex::trylock()
|
cannam@62
|
163 {
|
cannam@62
|
164 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
165 DWORD tid = GetCurrentThreadId();
|
cannam@62
|
166 #endif
|
cannam@62
|
167 DWORD result = WaitForSingleObject(m_mutex, 0);
|
cannam@62
|
168 if (result == WAIT_TIMEOUT || result == WAIT_FAILED) {
|
cannam@62
|
169 #ifdef DEBUG_MUTEX
|
cannam@62
|
170 cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl;
|
cannam@62
|
171 #endif
|
cannam@62
|
172 return false;
|
cannam@62
|
173 } else {
|
cannam@62
|
174 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
175 m_lockedBy = tid;
|
cannam@62
|
176 #endif
|
cannam@62
|
177 #ifdef DEBUG_MUTEX
|
cannam@62
|
178 cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl;
|
cannam@62
|
179 #endif
|
cannam@62
|
180 return true;
|
cannam@62
|
181 }
|
cannam@62
|
182 }
|
cannam@62
|
183
|
cannam@62
|
184 Condition::Condition(string name) :
|
cannam@62
|
185 m_locked(false)
|
cannam@62
|
186 #ifdef DEBUG_CONDITION
|
cannam@62
|
187 , m_name(name)
|
cannam@62
|
188 #endif
|
cannam@62
|
189 {
|
cannam@62
|
190 m_mutex = CreateMutex(NULL, FALSE, NULL);
|
cannam@62
|
191 m_condition = CreateEvent(NULL, FALSE, FALSE, NULL);
|
cannam@62
|
192 #ifdef DEBUG_CONDITION
|
cannam@62
|
193 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised condition " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
194 #endif
|
cannam@62
|
195 }
|
cannam@62
|
196
|
cannam@62
|
197 Condition::~Condition()
|
cannam@62
|
198 {
|
cannam@62
|
199 #ifdef DEBUG_CONDITION
|
cannam@62
|
200 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying condition " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
201 #endif
|
cannam@62
|
202 if (m_locked) ReleaseMutex(m_mutex);
|
cannam@62
|
203 CloseHandle(m_condition);
|
cannam@62
|
204 CloseHandle(m_mutex);
|
cannam@62
|
205 }
|
cannam@62
|
206
|
cannam@62
|
207 void
|
cannam@62
|
208 Condition::lock()
|
cannam@62
|
209 {
|
cannam@62
|
210 #ifdef DEBUG_CONDITION
|
cannam@62
|
211 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Want to lock " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
212 #endif
|
cannam@62
|
213 WaitForSingleObject(m_mutex, INFINITE);
|
cannam@62
|
214 m_locked = true;
|
cannam@62
|
215 #ifdef DEBUG_CONDITION
|
cannam@62
|
216 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Locked " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
217 #endif
|
cannam@62
|
218 }
|
cannam@62
|
219
|
cannam@62
|
220 void
|
cannam@62
|
221 Condition::unlock()
|
cannam@62
|
222 {
|
cannam@62
|
223 if (!m_locked) {
|
cannam@62
|
224 #ifdef DEBUG_CONDITION
|
cannam@62
|
225 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Not locked " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
226 #endif
|
cannam@62
|
227 return;
|
cannam@62
|
228 }
|
cannam@62
|
229 #ifdef DEBUG_CONDITION
|
cannam@62
|
230 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Unlocking " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
231 #endif
|
cannam@62
|
232 m_locked = false;
|
cannam@62
|
233 ReleaseMutex(m_mutex);
|
cannam@62
|
234 }
|
cannam@62
|
235
|
cannam@62
|
236 void
|
cannam@62
|
237 Condition::wait(int us)
|
cannam@62
|
238 {
|
cannam@62
|
239 if (us == 0) {
|
cannam@62
|
240
|
cannam@62
|
241 #ifdef DEBUG_CONDITION
|
cannam@62
|
242 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Waiting on " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
243 #endif
|
cannam@62
|
244 SignalObjectAndWait(m_mutex, m_condition, INFINITE, FALSE);
|
cannam@62
|
245 WaitForSingleObject(m_mutex, INFINITE);
|
cannam@62
|
246
|
cannam@62
|
247 } else {
|
cannam@62
|
248
|
cannam@62
|
249 DWORD ms = us / 1000;
|
cannam@62
|
250 if (us > 0 && ms == 0) ms = 1;
|
cannam@62
|
251
|
cannam@62
|
252 #ifdef DEBUG_CONDITION
|
cannam@62
|
253 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Timed waiting on " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
254 #endif
|
cannam@62
|
255 SignalObjectAndWait(m_mutex, m_condition, ms, FALSE);
|
cannam@62
|
256 WaitForSingleObject(m_mutex, INFINITE);
|
cannam@62
|
257 }
|
cannam@62
|
258
|
cannam@62
|
259 #ifdef DEBUG_CONDITION
|
cannam@62
|
260 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Wait done on " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
261 #endif
|
cannam@71
|
262
|
cannam@71
|
263 m_locked = true;
|
cannam@62
|
264 }
|
cannam@62
|
265
|
cannam@62
|
266 void
|
cannam@62
|
267 Condition::signal()
|
cannam@62
|
268 {
|
cannam@62
|
269 #ifdef DEBUG_CONDITION
|
cannam@62
|
270 cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Signalling " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
271 #endif
|
cannam@62
|
272 SetEvent(m_condition);
|
cannam@62
|
273 }
|
cannam@62
|
274
|
cannam@62
|
275 #else /* !_WIN32 */
|
cannam@62
|
276
|
cannam@62
|
277 #ifdef USE_PTHREADS
|
cannam@62
|
278
|
cannam@62
|
279 Thread::Thread() :
|
cannam@62
|
280 m_id(0),
|
cannam@62
|
281 m_extant(false)
|
cannam@62
|
282 {
|
cannam@62
|
283 #ifdef DEBUG_THREAD
|
cannam@62
|
284 cerr << "THREAD DEBUG: Created thread object " << this << endl;
|
cannam@62
|
285 #endif
|
cannam@62
|
286 }
|
cannam@62
|
287
|
cannam@62
|
288 Thread::~Thread()
|
cannam@62
|
289 {
|
cannam@62
|
290 #ifdef DEBUG_THREAD
|
cannam@62
|
291 cerr << "THREAD DEBUG: Destroying thread object " << this << ", id " << m_id << endl;
|
cannam@62
|
292 #endif
|
cannam@62
|
293 if (m_extant) {
|
cannam@62
|
294 pthread_join(m_id, 0);
|
cannam@62
|
295 }
|
cannam@62
|
296 #ifdef DEBUG_THREAD
|
cannam@62
|
297 cerr << "THREAD DEBUG: Destroyed thread object " << this << endl;
|
cannam@62
|
298 #endif
|
cannam@62
|
299 }
|
cannam@62
|
300
|
cannam@62
|
301 void
|
cannam@62
|
302 Thread::start()
|
cannam@62
|
303 {
|
cannam@62
|
304 if (pthread_create(&m_id, 0, staticRun, this)) {
|
cannam@62
|
305 cerr << "ERROR: thread creation failed" << endl;
|
cannam@62
|
306 exit(1);
|
cannam@62
|
307 } else {
|
cannam@62
|
308 #ifdef DEBUG_THREAD
|
cannam@62
|
309 cerr << "THREAD DEBUG: Created thread " << m_id << " for thread object " << this << endl;
|
cannam@62
|
310 #endif
|
cannam@62
|
311 m_extant = true;
|
cannam@62
|
312 }
|
cannam@62
|
313 }
|
cannam@62
|
314
|
cannam@62
|
315 void
|
cannam@62
|
316 Thread::wait()
|
cannam@62
|
317 {
|
cannam@62
|
318 if (m_extant) {
|
cannam@62
|
319 #ifdef DEBUG_THREAD
|
cannam@62
|
320 cerr << "THREAD DEBUG: Waiting on thread " << m_id << " for thread object " << this << endl;
|
cannam@62
|
321 #endif
|
cannam@62
|
322 pthread_join(m_id, 0);
|
cannam@62
|
323 #ifdef DEBUG_THREAD
|
cannam@62
|
324 cerr << "THREAD DEBUG: Waited on thread " << m_id << " for thread object " << this << endl;
|
cannam@62
|
325 #endif
|
cannam@62
|
326 m_extant = false;
|
cannam@62
|
327 }
|
cannam@62
|
328 }
|
cannam@62
|
329
|
cannam@62
|
330 Thread::Id
|
cannam@62
|
331 Thread::id()
|
cannam@62
|
332 {
|
cannam@62
|
333 return m_id;
|
cannam@62
|
334 }
|
cannam@62
|
335
|
cannam@62
|
336 bool
|
cannam@62
|
337 Thread::threadingAvailable()
|
cannam@62
|
338 {
|
cannam@62
|
339 return true;
|
cannam@62
|
340 }
|
cannam@62
|
341
|
cannam@62
|
342 void *
|
cannam@62
|
343 Thread::staticRun(void *arg)
|
cannam@62
|
344 {
|
cannam@62
|
345 Thread *thread = static_cast<Thread *>(arg);
|
cannam@62
|
346 #ifdef DEBUG_THREAD
|
cannam@62
|
347 cerr << "THREAD DEBUG: " << (void *)pthread_self() << ": Running thread " << thread->m_id << " for thread object " << thread << endl;
|
cannam@62
|
348 #endif
|
cannam@62
|
349 thread->run();
|
cannam@62
|
350 return 0;
|
cannam@62
|
351 }
|
cannam@62
|
352
|
cannam@62
|
353 Mutex::Mutex()
|
cannam@62
|
354 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
355 :
|
cannam@62
|
356 m_lockedBy(0),
|
cannam@62
|
357 m_locked(false)
|
cannam@62
|
358 #endif
|
cannam@62
|
359 {
|
cannam@62
|
360 pthread_mutex_init(&m_mutex, 0);
|
cannam@62
|
361 #ifdef DEBUG_MUTEX
|
cannam@62
|
362 cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Initialised mutex " << &m_mutex << endl;
|
cannam@62
|
363 #endif
|
cannam@62
|
364 }
|
cannam@62
|
365
|
cannam@62
|
366 Mutex::~Mutex()
|
cannam@62
|
367 {
|
cannam@62
|
368 #ifdef DEBUG_MUTEX
|
cannam@62
|
369 cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Destroying mutex " << &m_mutex << endl;
|
cannam@62
|
370 #endif
|
cannam@62
|
371 pthread_mutex_destroy(&m_mutex);
|
cannam@62
|
372 }
|
cannam@62
|
373
|
cannam@62
|
374 void
|
cannam@62
|
375 Mutex::lock()
|
cannam@62
|
376 {
|
cannam@62
|
377 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
378 pthread_t tid = pthread_self();
|
cannam@62
|
379 if (m_locked && m_lockedBy == tid) {
|
cannam@62
|
380 cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl;
|
cannam@62
|
381 }
|
cannam@62
|
382 #endif
|
cannam@62
|
383 #ifdef DEBUG_MUTEX
|
cannam@62
|
384 cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl;
|
cannam@62
|
385 #endif
|
cannam@62
|
386 pthread_mutex_lock(&m_mutex);
|
cannam@62
|
387 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
388 m_lockedBy = tid;
|
cannam@62
|
389 m_locked = true;
|
cannam@62
|
390 #endif
|
cannam@62
|
391 #ifdef DEBUG_MUTEX
|
cannam@62
|
392 cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl;
|
cannam@62
|
393 #endif
|
cannam@62
|
394 }
|
cannam@62
|
395
|
cannam@62
|
396 void
|
cannam@62
|
397 Mutex::unlock()
|
cannam@62
|
398 {
|
cannam@62
|
399 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
400 pthread_t tid = pthread_self();
|
cannam@62
|
401 if (!m_locked) {
|
cannam@62
|
402 cerr << "ERROR: Mutex " << &m_mutex << " not locked in unlock" << endl;
|
cannam@62
|
403 return;
|
cannam@62
|
404 } else if (m_lockedBy != tid) {
|
cannam@62
|
405 cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl;
|
cannam@62
|
406 return;
|
cannam@62
|
407 }
|
cannam@62
|
408 #endif
|
cannam@62
|
409 #ifdef DEBUG_MUTEX
|
cannam@62
|
410 cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl;
|
cannam@62
|
411 #endif
|
cannam@62
|
412 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
413 m_locked = false;
|
cannam@62
|
414 #endif
|
cannam@62
|
415 pthread_mutex_unlock(&m_mutex);
|
cannam@62
|
416 }
|
cannam@62
|
417
|
cannam@62
|
418 bool
|
cannam@62
|
419 Mutex::trylock()
|
cannam@62
|
420 {
|
cannam@62
|
421 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
422 pthread_t tid = pthread_self();
|
cannam@62
|
423 #endif
|
cannam@62
|
424 if (pthread_mutex_trylock(&m_mutex)) {
|
cannam@62
|
425 #ifdef DEBUG_MUTEX
|
cannam@62
|
426 cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl;
|
cannam@62
|
427 #endif
|
cannam@62
|
428 return false;
|
cannam@62
|
429 } else {
|
cannam@62
|
430 #ifndef NO_THREAD_CHECKS
|
cannam@62
|
431 m_lockedBy = tid;
|
cannam@62
|
432 m_locked = true;
|
cannam@62
|
433 #endif
|
cannam@62
|
434 #ifdef DEBUG_MUTEX
|
cannam@62
|
435 cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl;
|
cannam@62
|
436 #endif
|
cannam@62
|
437 return true;
|
cannam@62
|
438 }
|
cannam@62
|
439 }
|
cannam@62
|
440
|
cannam@62
|
441 Condition::Condition(string name) :
|
cannam@62
|
442 m_locked(false)
|
cannam@62
|
443 #ifdef DEBUG_CONDITION
|
cannam@62
|
444 , m_name(name)
|
cannam@62
|
445 #endif
|
cannam@62
|
446 {
|
cannam@62
|
447 pthread_mutex_init(&m_mutex, 0);
|
cannam@62
|
448 pthread_cond_init(&m_condition, 0);
|
cannam@62
|
449 #ifdef DEBUG_CONDITION
|
cannam@62
|
450 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Initialised condition " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
451 #endif
|
cannam@62
|
452 }
|
cannam@62
|
453
|
cannam@62
|
454 Condition::~Condition()
|
cannam@62
|
455 {
|
cannam@62
|
456 #ifdef DEBUG_CONDITION
|
cannam@62
|
457 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Destroying condition " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
458 #endif
|
cannam@62
|
459 if (m_locked) pthread_mutex_unlock(&m_mutex);
|
cannam@62
|
460 pthread_cond_destroy(&m_condition);
|
cannam@62
|
461 pthread_mutex_destroy(&m_mutex);
|
cannam@62
|
462 }
|
cannam@62
|
463
|
cannam@62
|
464 void
|
cannam@62
|
465 Condition::lock()
|
cannam@62
|
466 {
|
cannam@62
|
467 #ifdef DEBUG_CONDITION
|
cannam@62
|
468 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Want to lock " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
469 #endif
|
cannam@62
|
470 pthread_mutex_lock(&m_mutex);
|
cannam@62
|
471 m_locked = true;
|
cannam@62
|
472 #ifdef DEBUG_CONDITION
|
cannam@62
|
473 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Locked " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
474 #endif
|
cannam@62
|
475 }
|
cannam@62
|
476
|
cannam@62
|
477 void
|
cannam@62
|
478 Condition::unlock()
|
cannam@62
|
479 {
|
cannam@62
|
480 if (!m_locked) {
|
cannam@62
|
481 #ifdef DEBUG_CONDITION
|
cannam@62
|
482 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Not locked " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
483 #endif
|
cannam@62
|
484 return;
|
cannam@62
|
485 }
|
cannam@62
|
486 #ifdef DEBUG_CONDITION
|
cannam@62
|
487 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Unlocking " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
488 #endif
|
cannam@62
|
489 m_locked = false;
|
cannam@62
|
490 pthread_mutex_unlock(&m_mutex);
|
cannam@62
|
491 }
|
cannam@62
|
492
|
cannam@62
|
493 void
|
cannam@62
|
494 Condition::wait(int us)
|
cannam@62
|
495 {
|
cannam@62
|
496 if (us == 0) {
|
cannam@62
|
497
|
cannam@62
|
498 #ifdef DEBUG_CONDITION
|
cannam@62
|
499 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Waiting on " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
500 #endif
|
cannam@62
|
501 pthread_cond_wait(&m_condition, &m_mutex);
|
cannam@62
|
502
|
cannam@62
|
503 } else {
|
cannam@62
|
504
|
cannam@62
|
505 struct timeval now;
|
cannam@62
|
506 gettimeofday(&now, 0);
|
cannam@62
|
507
|
cannam@62
|
508 now.tv_usec += us;
|
cannam@62
|
509 while (now.tv_usec > 1000000) {
|
cannam@62
|
510 now.tv_usec -= 1000000;
|
cannam@62
|
511 ++now.tv_sec;
|
cannam@62
|
512 }
|
cannam@62
|
513
|
cannam@62
|
514 struct timespec timeout;
|
cannam@62
|
515 timeout.tv_sec = now.tv_sec;
|
cannam@62
|
516 timeout.tv_nsec = now.tv_usec * 1000;
|
cannam@62
|
517
|
cannam@62
|
518 #ifdef DEBUG_CONDITION
|
cannam@62
|
519 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Timed waiting on " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
520 #endif
|
cannam@62
|
521 pthread_cond_timedwait(&m_condition, &m_mutex, &timeout);
|
cannam@62
|
522 }
|
cannam@62
|
523
|
cannam@62
|
524 #ifdef DEBUG_CONDITION
|
cannam@62
|
525 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Wait done on " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
526 #endif
|
cannam@69
|
527
|
cannam@69
|
528 m_locked = true;
|
cannam@62
|
529 }
|
cannam@62
|
530
|
cannam@62
|
531 void
|
cannam@62
|
532 Condition::signal()
|
cannam@62
|
533 {
|
cannam@62
|
534 #ifdef DEBUG_CONDITION
|
cannam@62
|
535 cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Signalling " << &m_condition << " \"" << m_name << "\"" << endl;
|
cannam@62
|
536 #endif
|
cannam@62
|
537 pthread_cond_signal(&m_condition);
|
cannam@62
|
538 }
|
cannam@62
|
539
|
cannam@62
|
540 #else /* !USE_PTHREADS */
|
cannam@62
|
541
|
cannam@62
|
542 Thread::Thread()
|
cannam@62
|
543 {
|
cannam@62
|
544 }
|
cannam@62
|
545
|
cannam@62
|
546 Thread::~Thread()
|
cannam@62
|
547 {
|
cannam@62
|
548 }
|
cannam@62
|
549
|
cannam@62
|
550 void
|
cannam@62
|
551 Thread::start()
|
cannam@62
|
552 {
|
cannam@62
|
553 abort();
|
cannam@62
|
554 }
|
cannam@62
|
555
|
cannam@62
|
556 void
|
cannam@62
|
557 Thread::wait()
|
cannam@62
|
558 {
|
cannam@62
|
559 abort();
|
cannam@62
|
560 }
|
cannam@62
|
561
|
cannam@62
|
562 Thread::Id
|
cannam@62
|
563 Thread::id()
|
cannam@62
|
564 {
|
cannam@62
|
565 abort();
|
cannam@62
|
566 }
|
cannam@62
|
567
|
cannam@62
|
568 bool
|
cannam@62
|
569 Thread::threadingAvailable()
|
cannam@62
|
570 {
|
cannam@62
|
571 return false;
|
cannam@62
|
572 }
|
cannam@62
|
573
|
cannam@62
|
574 Mutex::Mutex()
|
cannam@62
|
575 {
|
cannam@62
|
576 }
|
cannam@62
|
577
|
cannam@62
|
578 Mutex::~Mutex()
|
cannam@62
|
579 {
|
cannam@62
|
580 }
|
cannam@62
|
581
|
cannam@62
|
582 void
|
cannam@62
|
583 Mutex::lock()
|
cannam@62
|
584 {
|
cannam@62
|
585 abort();
|
cannam@62
|
586 }
|
cannam@62
|
587
|
cannam@62
|
588 void
|
cannam@62
|
589 Mutex::unlock()
|
cannam@62
|
590 {
|
cannam@62
|
591 abort();
|
cannam@62
|
592 }
|
cannam@62
|
593
|
cannam@62
|
594 bool
|
cannam@62
|
595 Mutex::trylock()
|
cannam@62
|
596 {
|
cannam@62
|
597 abort();
|
cannam@62
|
598 }
|
cannam@62
|
599
|
cannam@62
|
600 Condition::Condition(const char *)
|
cannam@62
|
601 {
|
cannam@62
|
602 }
|
cannam@62
|
603
|
cannam@62
|
604 Condition::~Condition()
|
cannam@62
|
605 {
|
cannam@62
|
606 }
|
cannam@62
|
607
|
cannam@62
|
608 void
|
cannam@62
|
609 Condition::lock()
|
cannam@62
|
610 {
|
cannam@62
|
611 abort();
|
cannam@62
|
612 }
|
cannam@62
|
613
|
cannam@62
|
614 void
|
cannam@62
|
615 Condition::wait(int us)
|
cannam@62
|
616 {
|
cannam@62
|
617 abort();
|
cannam@62
|
618 }
|
cannam@62
|
619
|
cannam@62
|
620 void
|
cannam@62
|
621 Condition::signal()
|
cannam@62
|
622 {
|
cannam@62
|
623 abort();
|
cannam@62
|
624 }
|
cannam@62
|
625
|
cannam@62
|
626 #endif /* !USE_PTHREADS */
|
cannam@62
|
627 #endif /* !_WIN32 */
|
cannam@62
|
628
|
cannam@62
|
629 MutexLocker::MutexLocker(Mutex *mutex) :
|
cannam@62
|
630 m_mutex(mutex)
|
cannam@62
|
631 {
|
cannam@62
|
632 if (m_mutex) {
|
cannam@62
|
633 m_mutex->lock();
|
cannam@62
|
634 }
|
cannam@62
|
635 }
|
cannam@62
|
636
|
cannam@62
|
637 MutexLocker::~MutexLocker()
|
cannam@62
|
638 {
|
cannam@62
|
639 if (m_mutex) {
|
cannam@62
|
640 m_mutex->unlock();
|
cannam@62
|
641 }
|
cannam@62
|
642 }
|
cannam@62
|
643
|