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