/[svn]/linuxsampler/trunk/src/common/Condition.cpp
ViewVC logotype

Annotation of /linuxsampler/trunk/src/common/Condition.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1481 - (hide annotations) (download)
Wed Nov 14 23:42:15 2007 UTC (16 years, 6 months ago) by senoner
File size: 15961 byte(s)
* win32 port work in progress:
* - implemented win32 support in the following classes:
* Thread, Condition, Mutex, Path, LscpServer
* - lscp.y use DONTCARE instead of VOID
*  (a win32 symbol defined)
* - completed win32 editor plugin loader

1 schoenebeck 53 /***************************************************************************
2     * *
3     * LinuxSampler - modular, streaming capable sampler *
4     * *
5 schoenebeck 56 * Copyright (C) 2003, 2004 by Benno Senoner and Christian Schoenebeck *
6 schoenebeck 1221 * Copyright (C) 2005 - 2007 Christian Schoenebeck *
7 schoenebeck 53 * *
8     * This program is free software; you can redistribute it and/or modify *
9     * it under the terms of the GNU General Public License as published by *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13     * This program is distributed in the hope that it will be useful, *
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19     * along with this program; if not, write to the Free Software *
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24 persson 417 #include <sys/time.h>
25    
26 schoenebeck 53 #include "Condition.h"
27    
28 schoenebeck 1424 #include "global_private.h"
29 schoenebeck 63
30 senoner 1481 #if defined(WIN32)
31     //NOTE: since pthread_condattr_t is not needed in the Condition class so just set it to int
32     typedef int win32thread_condattr_t;
33    
34     typedef struct {
35     unsigned long tv_sec;
36     unsigned long tv_nsec;
37     } win32_timespec;
38    
39    
40     int win32thread_cond_init (win32thread_cond_t *cv, const win32thread_condattr_t *)
41     {
42     dmsg(7,("win32thread_cond_init:\n"));
43     cv->waiters_count_ = 0;
44     cv->was_broadcast_ = 0;
45     cv->sema_ = CreateSemaphore (NULL, // no security
46     0, // initially 0
47     0x7fffffff, // max count
48     NULL); // unnamed
49     dmsg(7,("win32thread_cond_init: after CreateSemaphore retval=%d\n",cv->sema_));
50     InitializeCriticalSection (&cv->waiters_count_lock_);
51     cv->waiters_done_ = CreateEvent (NULL, // no security
52     FALSE, // auto-reset
53     FALSE, // non-signaled initially
54     NULL); // unnamed
55     dmsg(7,("win32thread_cond_init: after CreateEvent retval=%d\n",cv->waiters_done_));
56    
57     return 0;
58     }
59    
60    
61     int win32thread_cond_destroy(win32thread_cond_t *cv) {
62     dmsg(7,("win32thread_cond_destroy ptr=%d\n",cv));
63     CloseHandle(cv->waiters_done_);
64     DeleteCriticalSection(&cv->waiters_count_lock_);
65     CloseHandle(cv->sema_);
66     return 0;
67     }
68    
69    
70    
71    
72     int win32thread_cond_timedwait (win32thread_cond_t *cv, win32thread_mutex_t *external_mutex, win32_timespec *timeout)
73     {
74     dmsg(7,("win32thread_cond_timedwait: external mutex=%d BEGIN!\n",external_mutex));
75     // Avoid race conditions.
76     dmsg(7,("win32thread_cond_timedwait: before EnterCriticalSection (&cv->waiters_count_lock_) cv->waiters_count_=%d\n",cv->waiters_count_));
77     EnterCriticalSection (&cv->waiters_count_lock_);
78     cv->waiters_count_++;
79     LeaveCriticalSection (&cv->waiters_count_lock_);
80     dmsg(7,("win32thread_cond_timedwait: after LeaveCriticalSection (&cv->waiters_count_lock_) cv->waiters_count_=%d\n",cv->waiters_count_));
81    
82    
83     // This call atomically releases the mutex and waits on the
84     // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
85     // are called by another thread.
86    
87     DWORD dwMilliseconds;
88     if(timeout->tv_sec || timeout->tv_nsec) {
89     dwMilliseconds = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000;
90     }
91     else {
92     dmsg(7,("win32thread_cond_timedwait: dwMilliseconds = INFINITE\n"));
93     dwMilliseconds = INFINITE;
94     }
95     dmsg(7,("win32thread_cond_timedwait: before SignalObjectAndWait(*external_mutex, cv->sema_, dwMilliseconds, FALSE), dwMilliseconds=%d\n",dwMilliseconds));
96     DWORD res;
97     res = SignalObjectAndWait (*external_mutex, cv->sema_, dwMilliseconds, FALSE);
98     dmsg(7,("win32thread_cond_timedwait: after SignalObjectAndWait, res=%d\n",res));
99     if(res == WAIT_TIMEOUT) return -1;
100    
101     // Reacquire lock to avoid race conditions.
102     dmsg(7,("win32thread_cond_timedwait: before EnterCriticalSection (2) (&cv->waiters_count_lock_) cv->waiters_count=%d\n",cv->waiters_count_));
103     EnterCriticalSection (&cv->waiters_count_lock_);
104     dmsg(7,("win32thread_cond_timedwait: after EnterCriticalSection (2) (&cv->waiters_count_lock_) cv->waiters_count=%d\n",cv->waiters_count_));
105    
106     // We're no longer waiting...
107     cv->waiters_count_--;
108    
109     // Check to see if we're the last waiter after <pthread_cond_broadcast>.
110     int last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
111    
112     LeaveCriticalSection (&cv->waiters_count_lock_);
113     dmsg(7,("win32thread_cond_timedwait: after LeaveCriticalSection (2) (&cv->waiters_count_lock_) last_waiter=%d\n",last_waiter));
114    
115     // If we're the last waiter thread during this particular broadcast
116     // then let all the other threads proceed.
117     if (last_waiter) {
118     // This call atomically signals the <waiters_done_> event and waits until
119     // it can acquire the <external_mutex>. This is required to ensure fairness.
120     dmsg(7,("win32thread_cond_timedwait: before SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE) \n"));
121     res = SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE);
122     dmsg(7,("win32thread_cond_timedwait: after SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE) res=%d\n",res));
123     if(res == WAIT_TIMEOUT) {
124     dmsg(7,("win32thread_cond_timedwait: after SignalObjectAndWait: WAIT_TIMEOUT! returning -1\n"));
125     return -1;
126     }
127     }
128     else {
129     // Always regain the external mutex since that's the guarantee we
130     // give to our callers.
131     dmsg(7,("win32thread_cond_timedwait: before WaitForSingleObject (*external_mutex, dwMilliseconds)\n"));
132     res = WaitForSingleObject (*external_mutex, dwMilliseconds);
133     dmsg(7,("win32thread_cond_timedwait: after WaitForSingleObject (*external_mutex, dwMilliseconds) res=%d\n",res));
134     if(res == WAIT_TIMEOUT) {
135     dmsg(7,("win32thread_cond_timedwait: after WaitForSingleObject: WAIT_TIMEOUT ! returning -1\n"));
136     return -1;
137     }
138     }
139     dmsg(7,("win32thread_cond_timedwait: all OK. returning 0\n"));
140     return 0;
141     }
142    
143     int win32thread_cond_signal (win32thread_cond_t *cv)
144     {
145    
146     dmsg(7,("win32thread_cond_signal cv=%d\n",cv));
147     dmsg(7,("win32thread_cond_signal before EnterCriticalSection (&cv->waiters_count_lock_)\n"));
148     EnterCriticalSection (&cv->waiters_count_lock_);
149     int have_waiters = cv->waiters_count_ > 0;
150     LeaveCriticalSection (&cv->waiters_count_lock_);
151     dmsg(7,("win32thread_cond_signal after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));
152    
153     dmsg(7,("win32thread_cond_signal have_waiters=%d\n",have_waiters));
154     // If there aren't any waiters, then this is a no-op.
155     if (have_waiters) {
156     dmsg(7,("win32thread_cond have_waiters is TRUE, before ReleaseSemaphore (cv->sema_, 1, 0)\n"));
157     ReleaseSemaphore (cv->sema_, 1, 0);
158     }
159     dmsg(7,("win32thread_cond_signal: all OK. returning 0\n"));
160     return 0;
161     }
162    
163     int win32thread_cond_wait (win32thread_cond_t *cv, win32thread_mutex_t *external_mutex) {
164     dmsg(7,("win32thread_cond_wait: (calls win32thread_cond_timedwait) cv=%d external_mutex=%d\n",cv, external_mutex));
165     win32_timespec timeout;
166     timeout.tv_sec = 0;
167     timeout.tv_nsec = 0;
168     return win32thread_cond_timedwait (cv, external_mutex, &timeout);
169     }
170    
171     int win32thread_cond_broadcast (win32thread_cond_t *cv)
172     {
173     DWORD res;
174     dmsg(7,("win32thread_cond_broadcast: cv=%d\n",cv));
175     dmsg(7,("win32thread_cond_broadcast: before EnterCriticalSection (&cv->waiters_count_lock_)\n"));
176     // This is needed to ensure that <waiters_count_> and <was_broadcast_> are
177     // consistent relative to each other.
178     EnterCriticalSection (&cv->waiters_count_lock_);
179     int have_waiters = 0;
180    
181     dmsg(7,("win32thread_cond_broadcast: cv->waiters_count_=%d\n",cv->waiters_count_));
182     if (cv->waiters_count_ > 0) {
183     dmsg(7,("win32thread_cond_broadcast: cv->waiters_count > 0 !\n"));
184     // We are broadcasting, even if there is just one waiter...
185     // Record that we are broadcasting, which helps optimize
186     // <pthread_cond_wait> for the non-broadcast case.
187     cv->was_broadcast_ = 1;
188     have_waiters = 1;
189     }
190     dmsg(7,("win32thread_cond_broadcast: cv->was_broadcast_=%d have_waiters=%d\n",cv->was_broadcast_,have_waiters));
191    
192     if (have_waiters) {
193     // Wake up all the waiters atomically.
194     dmsg(7,("win32thread_cond_broadcast: have_waiters ! before ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);\n"));
195     ReleaseSemaphore (cv->sema_, cv->waiters_count_, 0);
196    
197     LeaveCriticalSection (&cv->waiters_count_lock_);
198     dmsg(7,("win32thread_cond_broadcast: have_waiters ! after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));
199    
200     // Wait for all the awakened threads to acquire the counting
201     // semaphore.
202     dmsg(7,("win32thread_cond_broadcast: before WaitForSingleObject (cv->waiters_done_, INFINITE)\n"));
203     res = WaitForSingleObject (cv->waiters_done_, INFINITE);
204     dmsg(7,("win32thread_cond_broadcast: after WaitForSingleObject (cv->waiters_done_, INFINITE) res=%d\n",res));
205     // This assignment is okay, even without the <waiters_count_lock_> held
206     // because no other waiter threads can wake up to access it.
207     cv->was_broadcast_ = 0;
208     }
209     else {
210     LeaveCriticalSection (&cv->waiters_count_lock_);
211     dmsg(7,("win32thread_cond_broadcast: after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));
212     }
213     dmsg(7,("win32thread_cond_broadcast: all OK, returning 0.\n"));
214     return 0;
215     }
216    
217    
218    
219     #endif
220    
221    
222 schoenebeck 880 namespace LinuxSampler {
223    
224 schoenebeck 53 Condition::Condition(bool bInitialCondition) {
225 senoner 1481 dmsg(7,("Condition:: constructor, bInitialCondition=%d\n", bInitialCondition));
226     #if defined(WIN32)
227     win32thread_cond_init(&__win32_true_condition, NULL);
228     win32thread_cond_init(&__win32_false_condition, NULL);
229     #else
230 schoenebeck 53 pthread_cond_init(&__posix_true_condition, NULL);
231     pthread_cond_init(&__posix_false_condition, NULL);
232 senoner 1481 #endif
233 schoenebeck 53 bCondition = bInitialCondition;
234     }
235    
236     Condition::~Condition() {
237 senoner 1481 #if defined(WIN32)
238     win32thread_cond_destroy(&__win32_true_condition);
239     win32thread_cond_destroy(&__win32_false_condition);
240     #else
241 schoenebeck 53 pthread_cond_destroy(&__posix_true_condition);
242     pthread_cond_destroy(&__posix_false_condition);
243 senoner 1481 #endif
244 schoenebeck 53 }
245    
246     int Condition::WaitIf(bool bCondition, long TimeoutSeconds, long TimeoutNanoSeconds) {
247 senoner 1481 dmsg(7,("Condition::WaitIf: bCondition=%d TimeoutSeconds=%d TimeoutNanoSeconds=%d\n",bCondition, TimeoutSeconds, TimeoutNanoSeconds));
248 schoenebeck 63 dmsg(7,("Condition::Waitif() -> LOCK()\n"));
249 schoenebeck 53 Lock();
250 schoenebeck 63 dmsg(7,("Condition::Waitif() -> LOCK() passed\n"));
251 schoenebeck 53 int res = 0;
252     if (this->bCondition == bCondition) {
253 schoenebeck 63 if (bCondition) { // wait until condition turned 'false'
254 senoner 1481 #if defined(WIN32)
255     win32_timespec timeout;
256     timeout.tv_sec = TimeoutSeconds;
257     timeout.tv_nsec = TimeoutNanoSeconds;
258     dmsg(7,("Condition::Waitif() -> waiting for 'false' condition with timeout\n"));
259     res = win32thread_cond_timedwait(&__win32_false_condition, &hMutex, &timeout);
260     dmsg(7,("Condition::Waitif() -> awakened from 'false' condition waiting\n"));
261     #else
262 schoenebeck 63 if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout
263 persson 417 struct timeval now;
264     gettimeofday(&now, 0);
265 schoenebeck 53 timespec timeout;
266 persson 417 timeout.tv_sec = now.tv_sec + TimeoutSeconds;
267     timeout.tv_nsec = now.tv_usec * 1000 + TimeoutNanoSeconds;
268 schoenebeck 63 dmsg(7,("Condition::Waitif() -> waiting for 'false' condition with timeout\n"));
269 schoenebeck 53 res = pthread_cond_timedwait(&__posix_false_condition, &__posix_mutex, &timeout);
270 schoenebeck 63 dmsg(7,("Condition::Waitif() -> awakened from 'false' condition waiting\n"));
271 schoenebeck 53 }
272 schoenebeck 63 else { // wait without timeout
273     dmsg(7,("Condition::Waitif() -> waiting for 'false' condition\n"));
274     pthread_cond_wait(&__posix_false_condition, &__posix_mutex);
275     dmsg(7,("Condition::Waitif() -> awakened from 'false' condition waiting\n"));
276     }
277 senoner 1481 #endif
278 schoenebeck 53 }
279 schoenebeck 63 else { // wait until condition turned 'true'
280 senoner 1481 #if defined(WIN32)
281     win32_timespec timeout;
282     timeout.tv_sec = TimeoutSeconds;
283     timeout.tv_nsec = TimeoutNanoSeconds;
284     dmsg(7,("Condition::Waitif() -> waiting for 'true' condition with timeout\n"));
285     res = win32thread_cond_timedwait(&__win32_true_condition, &hMutex, &timeout);
286     dmsg(7,("Condition::Waitif() -> awakened from 'true' condition waiting\n"));
287     #else
288 schoenebeck 63 if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout
289 persson 417 struct timeval now;
290     gettimeofday(&now, 0);
291 schoenebeck 53 timespec timeout;
292 persson 417 timeout.tv_sec = now.tv_sec + TimeoutSeconds;
293     timeout.tv_nsec = now.tv_usec * 1000 + TimeoutNanoSeconds;
294 schoenebeck 63 dmsg(7,("Condition::Waitif() -> waiting for 'true' condition with timeout\n"));
295 schoenebeck 53 res = pthread_cond_timedwait(&__posix_true_condition, &__posix_mutex, &timeout);
296 schoenebeck 63 dmsg(7,("Condition::Waitif() -> awakened from 'true' condition waiting\n"));
297 schoenebeck 53 }
298 schoenebeck 63 else { // wait without timeout
299     dmsg(7,("Condition::Waitif() -> waiting for 'true' condition\n"));
300     pthread_cond_wait(&__posix_true_condition, &__posix_mutex);
301     dmsg(7,("Condition::Waitif() -> awakened from 'true' condition waiting\n"));
302     }
303 senoner 1481 #endif
304 schoenebeck 53 }
305     }
306     return res;
307     }
308    
309     int Condition::WaitAndUnlockIf(bool bCondition, long TimeoutSeconds, long TimeoutNanoSeconds) {
310     int res = WaitIf(bCondition, TimeoutSeconds, TimeoutNanoSeconds);
311 schoenebeck 63 dmsg(7,("Condition::WaitAndUnlockIf() -> UNLOCK()\n"));
312 schoenebeck 53 Unlock();
313 schoenebeck 63 dmsg(7,("Condition::WaitAndUnlockIf() -> UNLOCK() passed\n"));
314 schoenebeck 53 return res;
315     }
316    
317     void Condition::Set(bool bCondition) {
318 schoenebeck 63 dmsg(7,("Condition::Set() -> LOCK()\n"));
319 schoenebeck 53 Lock();
320 schoenebeck 63 dmsg(7,("Condition::Set() -> LOCK() passed\n"));
321 schoenebeck 53 if (this->bCondition != bCondition) {
322     this->bCondition = bCondition;
323 schoenebeck 63 if (bCondition) {
324     dmsg(7,("Condition::Set() -> broadcasting 'true' condition\n"));
325 senoner 1481 #if defined(WIN32)
326     win32thread_cond_broadcast(&__win32_true_condition);
327     #else
328 schoenebeck 63 pthread_cond_broadcast(&__posix_true_condition);
329 senoner 1481 #endif
330 schoenebeck 63 }
331     else {
332     dmsg(7,("Condition::Set() -> broadcasting 'false' condition\n"));
333 senoner 1481 #if defined(WIN32)
334     win32thread_cond_broadcast(&__win32_false_condition);
335     #else
336 schoenebeck 63 pthread_cond_broadcast(&__posix_false_condition);
337 senoner 1481 #endif
338 schoenebeck 63 }
339 schoenebeck 53 }
340 schoenebeck 63 Unlock();
341 schoenebeck 53 }
342 schoenebeck 880
343 schoenebeck 1221 bool Condition::GetUnsafe() {
344     return bCondition;
345     }
346    
347 schoenebeck 880 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC