1 /* 2 * Copyright (C) 2002 - David W. Durham 3 * 4 * This file is part of ReZound, an audio editing application. 5 * 6 * ReZound is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published 8 * by the Free Software Foundation; either version 2 of the License, 9 * or (at your option) any later version. 10 * 11 * ReZound is distributed in the hope that it will be useful, but 12 * WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 19 */ 20 #ifndef __CConditionVariable_H__ 21 #define __CConditionVariable_H__ 22 23 #include "../../config/common.h" 24 25 /* 26 * This is a multi-platform condition variable wrapper. 27 * 28 * Its public interface looks like: 29 30 class CConditionVariable 31 { 32 public: 33 CConditionVariable(); 34 virtual ~CConditionVariable() throw(); 35 36 // returns false if it timed out, else true 37 // NOTE: if timeout is >= 0, and wait() returns false, there's no guarantee that the condition-predicate is false, so it may need to be checked 38 bool wait(CMutex &mutex,int timeout=-1); 39 40 void signal(); // slightly more efficient if there is only going to be a single waiter 41 void broadcast(); // use if there are multiple waiters 42 }; 43 44 45 --------------------------------------------------------------------------- 46 47 Example use: 48 49 CMutex m; 50 CConditionVariable c; 51 52 // --- code that waits for condition to be true ----- 53 54 m.lock(); 55 while(desired condition IS NOT true) 56 c.wait(m); // the thread will wake up every time the condition variable is signaled.. 57 58 // now condition IS true 59 ... 60 m.unlock(); 61 62 ... 63 64 65 // --- code that causes condition to be true ------ 66 67 m.lock(); 68 ... something that causes condition to be true ... 69 c.broadcast(); (or c.signal()) 70 m.unlock(); 71 72 ... 73 74 75 76 Now, if it can be known that only one thread will ever 77 be waiting on the condition, c.signal() can be used 78 to be more efficient. In doubt, use c.broadcast() 79 broadcast() wakes up all the threads waiting 80 81 Also, a waiting thread is not supposed to wake up until 82 a signaler *unlocks* the mutex. Hence signal() can 83 be called before or after the condition is actually true 84 as long as it's done while the mutex is locked. 85 */ 86 87 #include "CMutex.h" 88 89 #if defined(_WIN32) 90 // *** WIN32 implementation *** 91 92 // doing this to avoid including windows.h 93 // must use this below because CRITICAL_SECTION is a typedef and it causes internal compiler errors 94 struct _RTL_CRITICAL_SECTION; 95 96 class CConditionVariable 97 { 98 public: 99 100 CConditionVariable(); 101 ~CConditionVariable() throw(); 102 103 // returns false if it timed out, else true 104 // NOTE: if timeout is >= 0, and wait() returns false, there's no guarantee that the condition-predicate is false, so it may need to be checked 105 bool wait(CMutex &mutex,int timeout_ms=-1); 106 107 void signal(); 108 109 void broadcast(); 110 111 private: 112 113 enum { 114 SIGNAL = 0, 115 BROADCAST = 1, 116 MAX_EVENTS = 2 117 }; 118 119 // Count of the number of waiters. 120 unsigned waiters_count_; 121 122 // Serialize access to <waiters_count_>. 123 _RTL_CRITICAL_SECTION *waiters_count_lock_; 124 125 // Signal and broadcast event HANDLEs. 126 void* events_[MAX_EVENTS]; // ??? would make this HANDLE, but really don't think I need to include a huge windows.h header file for a void * typedef 127 128 }; 129 130 #else 131 // *** posix implementation *** 132 133 #include <pthread.h> 134 135 class CConditionVariable 136 { 137 public: 138 139 CConditionVariable(); 140 virtual ~CConditionVariable() throw(); 141 142 // returns false if it timed out, else true 143 // NOTE: if timeout is >= 0, and wait() returns false, there's no guarantee that the condition-predicate is false, so it may need to be checked 144 bool wait(CMutex &mutex,int timeout=-1); 145 146 void signal(); 147 148 void broadcast(); 149 150 private: 151 pthread_cond_t cond; 152 153 }; 154 155 #endif 156 157 #endif 158