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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1481 by senoner, Wed Nov 14 23:42:15 2007 UTC revision 1560 by schoenebeck, Thu Dec 6 17:19:16 2007 UTC
# Line 27  Line 27 
27    
28  #include "global_private.h"  #include "global_private.h"
29    
30    namespace LinuxSampler {
31    
32    // *************** Internal data types (for Windows only) ***************
33    // *
34    
35  #if defined(WIN32)  #if defined(WIN32)
36    
37    typedef HANDLE win32thread_mutex_t;
38    
39  //NOTE: since pthread_condattr_t is not needed in the Condition class so just set it to int  //NOTE: since pthread_condattr_t is not needed in the Condition class so just set it to int
40  typedef int win32thread_condattr_t;  typedef int win32thread_condattr_t;
41    
42  typedef struct {  typedef struct {
43                      unsigned long tv_sec;      unsigned long tv_sec;
44                      unsigned long tv_nsec;      unsigned long tv_nsec;
45                  } win32_timespec;  } win32_timespec;
46    
47    
48  int win32thread_cond_init (win32thread_cond_t *cv, const win32thread_condattr_t *)  
49    // *************** ConditionInternal (for Windows only) ***************
50    // *
51    
52    class ConditionInternal {
53    public:
54    
55    static
56    int win32thread_cond_init (Condition::win32thread_cond_t *cv, const win32thread_condattr_t *)
57  {  {
58      dmsg(7,("win32thread_cond_init:\n"));      dmsg(7,("win32thread_cond_init:\n"));
59      cv->waiters_count_ = 0;      cv->waiters_count_ = 0;
# Line 45  int win32thread_cond_init (win32thread_c Line 61  int win32thread_cond_init (win32thread_c
61      cv->sema_ = CreateSemaphore (NULL,       // no security      cv->sema_ = CreateSemaphore (NULL,       // no security
62                                   0,          // initially 0                                   0,          // initially 0
63                                   0x7fffffff, // max count                                   0x7fffffff, // max count
64                                   NULL);      // unnamed                                   NULL);      // unnamed
65      dmsg(7,("win32thread_cond_init: after CreateSemaphore retval=%d\n",cv->sema_));                                                                    dmsg(7,("win32thread_cond_init: after CreateSemaphore retval=%d\n",cv->sema_));
66      InitializeCriticalSection (&cv->waiters_count_lock_);      InitializeCriticalSection (&cv->waiters_count_lock_);
67      cv->waiters_done_ = CreateEvent (NULL,  // no security      cv->waiters_done_ = CreateEvent (NULL,  // no security
68                                     FALSE, // auto-reset                                     FALSE, // auto-reset
69                                     FALSE, // non-signaled initially                                     FALSE, // non-signaled initially
70                                     NULL); // unnamed                                     NULL); // unnamed
71      dmsg(7,("win32thread_cond_init: after CreateEvent retval=%d\n",cv->waiters_done_));                                                                  dmsg(7,("win32thread_cond_init: after CreateEvent retval=%d\n",cv->waiters_done_));
72                                                                      
73      return 0;      return 0;
74  }  }
75    
76    static
77  int win32thread_cond_destroy(win32thread_cond_t *cv) {  int win32thread_cond_destroy(Condition::win32thread_cond_t *cv) {
78    dmsg(7,("win32thread_cond_destroy ptr=%d\n",cv));        dmsg(7,("win32thread_cond_destroy ptr=%d\n",cv));
79    CloseHandle(cv->waiters_done_);    CloseHandle(cv->waiters_done_);
80    DeleteCriticalSection(&cv->waiters_count_lock_);    DeleteCriticalSection(&cv->waiters_count_lock_);
81    CloseHandle(cv->sema_);    CloseHandle(cv->sema_);
82    return 0;    return 0;
83  }  }
84    
85    static
86    int win32thread_cond_timedwait (Condition::win32thread_cond_t *cv, win32thread_mutex_t *external_mutex, win32_timespec *timeout)
   
 int win32thread_cond_timedwait (win32thread_cond_t *cv, win32thread_mutex_t *external_mutex, win32_timespec *timeout)  
87  {  {
88      dmsg(7,("win32thread_cond_timedwait: external mutex=%d BEGIN!\n",external_mutex));        dmsg(7,("win32thread_cond_timedwait: external mutex=%d BEGIN!\n",external_mutex));
89      // Avoid race conditions.      // Avoid race conditions.
90      dmsg(7,("win32thread_cond_timedwait: before EnterCriticalSection (&cv->waiters_count_lock_) cv->waiters_count_=%d\n",cv->waiters_count_));      dmsg(7,("win32thread_cond_timedwait: before EnterCriticalSection (&cv->waiters_count_lock_) cv->waiters_count_=%d\n",cv->waiters_count_));
91      EnterCriticalSection (&cv->waiters_count_lock_);      EnterCriticalSection (&cv->waiters_count_lock_);
92      cv->waiters_count_++;      cv->waiters_count_++;
93      LeaveCriticalSection (&cv->waiters_count_lock_);      LeaveCriticalSection (&cv->waiters_count_lock_);
94      dmsg(7,("win32thread_cond_timedwait: after LeaveCriticalSection (&cv->waiters_count_lock_) cv->waiters_count_=%d\n",cv->waiters_count_));      dmsg(7,("win32thread_cond_timedwait: after LeaveCriticalSection (&cv->waiters_count_lock_) cv->waiters_count_=%d\n",cv->waiters_count_));
95            
96    
97      // This call atomically releases the mutex and waits on the      // This call atomically releases the mutex and waits on the
98      // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>      // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
99      // are called by another thread.      // are called by another thread.
100      
101      DWORD dwMilliseconds;      DWORD dwMilliseconds;
102      if(timeout->tv_sec || timeout->tv_nsec) {      if(timeout->tv_sec || timeout->tv_nsec) {
103          dwMilliseconds = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000;          dwMilliseconds = timeout->tv_sec * 1000 + timeout->tv_nsec / 1000000;
# Line 96  int win32thread_cond_timedwait (win32thr Line 110  int win32thread_cond_timedwait (win32thr
110      DWORD res;      DWORD res;
111      res = SignalObjectAndWait (*external_mutex, cv->sema_, dwMilliseconds, FALSE);      res = SignalObjectAndWait (*external_mutex, cv->sema_, dwMilliseconds, FALSE);
112      dmsg(7,("win32thread_cond_timedwait: after SignalObjectAndWait, res=%d\n",res));      dmsg(7,("win32thread_cond_timedwait: after SignalObjectAndWait, res=%d\n",res));
113      if(res == WAIT_TIMEOUT) return -1;      if(res == WAIT_TIMEOUT) return -1;
114    
115      // Reacquire lock to avoid race conditions.      // Reacquire lock to avoid race conditions.
116      dmsg(7,("win32thread_cond_timedwait: before EnterCriticalSection (2) (&cv->waiters_count_lock_) cv->waiters_count=%d\n",cv->waiters_count_));      dmsg(7,("win32thread_cond_timedwait: before EnterCriticalSection (2) (&cv->waiters_count_lock_) cv->waiters_count=%d\n",cv->waiters_count_));
117      EnterCriticalSection (&cv->waiters_count_lock_);      EnterCriticalSection (&cv->waiters_count_lock_);
118      dmsg(7,("win32thread_cond_timedwait: after EnterCriticalSection (2) (&cv->waiters_count_lock_) cv->waiters_count=%d\n",cv->waiters_count_));      dmsg(7,("win32thread_cond_timedwait: after EnterCriticalSection (2) (&cv->waiters_count_lock_) cv->waiters_count=%d\n",cv->waiters_count_));
119    
120      // We're no longer waiting...      // We're no longer waiting...
121      cv->waiters_count_--;      cv->waiters_count_--;
# Line 110  int win32thread_cond_timedwait (win32thr Line 124  int win32thread_cond_timedwait (win32thr
124      int last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;      int last_waiter = cv->was_broadcast_ && cv->waiters_count_ == 0;
125    
126      LeaveCriticalSection (&cv->waiters_count_lock_);      LeaveCriticalSection (&cv->waiters_count_lock_);
127      dmsg(7,("win32thread_cond_timedwait: after LeaveCriticalSection (2) (&cv->waiters_count_lock_) last_waiter=%d\n",last_waiter));      dmsg(7,("win32thread_cond_timedwait: after LeaveCriticalSection (2) (&cv->waiters_count_lock_) last_waiter=%d\n",last_waiter));
128    
129      // If we're the last waiter thread during this particular broadcast      // If we're the last waiter thread during this particular broadcast
130      // then let all the other threads proceed.      // then let all the other threads proceed.
131      if (last_waiter) {      if (last_waiter) {
132          // This call atomically signals the <waiters_done_> event and waits until          // This call atomically signals the <waiters_done_> event and waits until
133          // it can acquire the <external_mutex>.  This is required to ensure fairness.          // it can acquire the <external_mutex>.  This is required to ensure fairness.
134          dmsg(7,("win32thread_cond_timedwait: before SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE) \n"));          dmsg(7,("win32thread_cond_timedwait: before SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE) \n"));
135          res = SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE);          res = SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE);
136          dmsg(7,("win32thread_cond_timedwait: after SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE) res=%d\n",res));          dmsg(7,("win32thread_cond_timedwait: after SignalObjectAndWait (cv->waiters_done_, *external_mutex, dwMilliseconds, FALSE) res=%d\n",res));
# Line 127  int win32thread_cond_timedwait (win32thr Line 141  int win32thread_cond_timedwait (win32thr
141      }      }
142      else {      else {
143          // Always regain the external mutex since that's the guarantee we          // Always regain the external mutex since that's the guarantee we
144          // give to our callers.          // give to our callers.
145          dmsg(7,("win32thread_cond_timedwait: before WaitForSingleObject (*external_mutex, dwMilliseconds)\n"));          dmsg(7,("win32thread_cond_timedwait: before WaitForSingleObject (*external_mutex, dwMilliseconds)\n"));
146          res = WaitForSingleObject (*external_mutex, dwMilliseconds);          res = WaitForSingleObject (*external_mutex, dwMilliseconds);
147          dmsg(7,("win32thread_cond_timedwait: after WaitForSingleObject (*external_mutex, dwMilliseconds) res=%d\n",res));          dmsg(7,("win32thread_cond_timedwait: after WaitForSingleObject (*external_mutex, dwMilliseconds) res=%d\n",res));
# Line 140  int win32thread_cond_timedwait (win32thr Line 154  int win32thread_cond_timedwait (win32thr
154      return 0;      return 0;
155  }  }
156    
157  int win32thread_cond_signal (win32thread_cond_t *cv)  static
158  {  int win32thread_cond_broadcast (Condition::win32thread_cond_t *cv)
   
     dmsg(7,("win32thread_cond_signal cv=%d\n",cv));  
     dmsg(7,("win32thread_cond_signal before EnterCriticalSection (&cv->waiters_count_lock_)\n"));  
     EnterCriticalSection (&cv->waiters_count_lock_);  
     int have_waiters = cv->waiters_count_ > 0;  
     LeaveCriticalSection (&cv->waiters_count_lock_);  
     dmsg(7,("win32thread_cond_signal after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));  
   
     dmsg(7,("win32thread_cond_signal have_waiters=%d\n",have_waiters));  
     // If there aren't any waiters, then this is a no-op.    
     if (have_waiters) {  
         dmsg(7,("win32thread_cond have_waiters is TRUE,  before ReleaseSemaphore (cv->sema_, 1, 0)\n"));  
         ReleaseSemaphore (cv->sema_, 1, 0);  
     }  
     dmsg(7,("win32thread_cond_signal: all OK. returning 0\n"));  
     return 0;  
 }  
   
 int win32thread_cond_wait (win32thread_cond_t *cv, win32thread_mutex_t *external_mutex) {  
     dmsg(7,("win32thread_cond_wait: (calls win32thread_cond_timedwait)  cv=%d  external_mutex=%d\n",cv, external_mutex));  
     win32_timespec timeout;  
     timeout.tv_sec = 0;  
     timeout.tv_nsec = 0;  
     return win32thread_cond_timedwait (cv, external_mutex, &timeout);  
 }  
   
 int win32thread_cond_broadcast (win32thread_cond_t *cv)  
159  {  {
160      DWORD res;      DWORD res;
161      dmsg(7,("win32thread_cond_broadcast: cv=%d\n",cv));      dmsg(7,("win32thread_cond_broadcast: cv=%d\n",cv));
# Line 198  int win32thread_cond_broadcast (win32thr Line 185  int win32thread_cond_broadcast (win32thr
185          dmsg(7,("win32thread_cond_broadcast: have_waiters ! after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));          dmsg(7,("win32thread_cond_broadcast: have_waiters ! after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));
186    
187          // Wait for all the awakened threads to acquire the counting          // Wait for all the awakened threads to acquire the counting
188          // semaphore.          // semaphore.
189          dmsg(7,("win32thread_cond_broadcast: before WaitForSingleObject (cv->waiters_done_, INFINITE)\n"));          dmsg(7,("win32thread_cond_broadcast: before WaitForSingleObject (cv->waiters_done_, INFINITE)\n"));
190          res = WaitForSingleObject (cv->waiters_done_, INFINITE);          res = WaitForSingleObject (cv->waiters_done_, INFINITE);
191          dmsg(7,("win32thread_cond_broadcast: after WaitForSingleObject (cv->waiters_done_, INFINITE) res=%d\n",res));          dmsg(7,("win32thread_cond_broadcast: after WaitForSingleObject (cv->waiters_done_, INFINITE) res=%d\n",res));
192          // This assignment is okay, even without the <waiters_count_lock_> held          // This assignment is okay, even without the <waiters_count_lock_> held
193          // because no other waiter threads can wake up to access it.          // because no other waiter threads can wake up to access it.
194          cv->was_broadcast_ = 0;          cv->was_broadcast_ = 0;
195      }      }
# Line 210  int win32thread_cond_broadcast (win32thr Line 197  int win32thread_cond_broadcast (win32thr
197          LeaveCriticalSection (&cv->waiters_count_lock_);          LeaveCriticalSection (&cv->waiters_count_lock_);
198          dmsg(7,("win32thread_cond_broadcast: after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));          dmsg(7,("win32thread_cond_broadcast: after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));
199      }      }
200          dmsg(7,("win32thread_cond_broadcast: all OK, returning 0.\n"));      dmsg(7,("win32thread_cond_broadcast: all OK, returning 0.\n"));
201      return 0;      return 0;
202  }  }
203    
204    /* TODO: the following two functions are currently not used yet
205    static
206    int win32thread_cond_signal (Condition::win32thread_cond_t *cv)
207    {
208    
209        dmsg(7,("win32thread_cond_signal cv=%d\n",cv));
210        dmsg(7,("win32thread_cond_signal before EnterCriticalSection (&cv->waiters_count_lock_)\n"));
211        EnterCriticalSection (&cv->waiters_count_lock_);
212        int have_waiters = cv->waiters_count_ > 0;
213        LeaveCriticalSection (&cv->waiters_count_lock_);
214        dmsg(7,("win32thread_cond_signal after LeaveCriticalSection (&cv->waiters_count_lock_)\n"));
215    
216  #endif      dmsg(7,("win32thread_cond_signal have_waiters=%d\n",have_waiters));
217        // If there aren't any waiters, then this is a no-op.
218        if (have_waiters) {
219            dmsg(7,("win32thread_cond have_waiters is TRUE,  before ReleaseSemaphore (cv->sema_, 1, 0)\n"));
220            ReleaseSemaphore (cv->sema_, 1, 0);
221        }
222        dmsg(7,("win32thread_cond_signal: all OK. returning 0\n"));
223        return 0;
224    }
225    
226    static
227    int win32thread_cond_wait (Condition::win32thread_cond_t *cv, win32thread_mutex_t *external_mutex) {
228        dmsg(7,("win32thread_cond_wait: (calls win32thread_cond_timedwait)  cv=%d  external_mutex=%d\n",cv, external_mutex));
229        win32_timespec timeout;
230        timeout.tv_sec = 0;
231        timeout.tv_nsec = 0;
232        return win32thread_cond_timedwait (cv, external_mutex, &timeout);
233    }
234    */
235    
236    }; // class ConditionInternal
237    
238  namespace LinuxSampler {  #endif // WIN32
239    
240    
241    
242    // *************** Condition ***************
243    // *
244    
245  Condition::Condition(bool bInitialCondition) {  Condition::Condition(bool bInitialCondition) {
246  dmsg(7,("Condition:: constructor, bInitialCondition=%d\n", bInitialCondition));  dmsg(7,("Condition:: constructor, bInitialCondition=%d\n", bInitialCondition));
247  #if defined(WIN32)  #if defined(WIN32)
248      win32thread_cond_init(&__win32_true_condition, NULL);      ConditionInternal::win32thread_cond_init(&__win32_true_condition, NULL);
249      win32thread_cond_init(&__win32_false_condition, NULL);      ConditionInternal::win32thread_cond_init(&__win32_false_condition, NULL);
250  #else  #else
251      pthread_cond_init(&__posix_true_condition, NULL);      pthread_cond_init(&__posix_true_condition, NULL);
252      pthread_cond_init(&__posix_false_condition, NULL);      pthread_cond_init(&__posix_false_condition, NULL);
253  #endif    #endif
254      bCondition = bInitialCondition;      bCondition = bInitialCondition;
255  }  }
256    
257  Condition::~Condition() {  Condition::~Condition() {
258  #if defined(WIN32)  #if defined(WIN32)
259      win32thread_cond_destroy(&__win32_true_condition);      ConditionInternal::win32thread_cond_destroy(&__win32_true_condition);
260      win32thread_cond_destroy(&__win32_false_condition);      ConditionInternal::win32thread_cond_destroy(&__win32_false_condition);
261  #else  #else
262      pthread_cond_destroy(&__posix_true_condition);      pthread_cond_destroy(&__posix_true_condition);
263      pthread_cond_destroy(&__posix_false_condition);      pthread_cond_destroy(&__posix_false_condition);
# Line 256  int Condition::WaitIf(bool bCondition, l Line 277  int Condition::WaitIf(bool bCondition, l
277              timeout.tv_sec  = TimeoutSeconds;              timeout.tv_sec  = TimeoutSeconds;
278              timeout.tv_nsec = TimeoutNanoSeconds;              timeout.tv_nsec = TimeoutNanoSeconds;
279              dmsg(7,("Condition::Waitif() -> waiting for 'false' condition with timeout\n"));              dmsg(7,("Condition::Waitif() -> waiting for 'false' condition with timeout\n"));
280              res = win32thread_cond_timedwait(&__win32_false_condition, &hMutex, &timeout);              res = ConditionInternal::win32thread_cond_timedwait(&__win32_false_condition, &hMutex, &timeout);
281              dmsg(7,("Condition::Waitif() -> awakened from 'false' condition waiting\n"));              dmsg(7,("Condition::Waitif() -> awakened from 'false' condition waiting\n"));
282              #else              #else
283              if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout              if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout
# Line 282  int Condition::WaitIf(bool bCondition, l Line 303  int Condition::WaitIf(bool bCondition, l
303              timeout.tv_sec  = TimeoutSeconds;              timeout.tv_sec  = TimeoutSeconds;
304              timeout.tv_nsec = TimeoutNanoSeconds;              timeout.tv_nsec = TimeoutNanoSeconds;
305              dmsg(7,("Condition::Waitif() -> waiting for 'true' condition with timeout\n"));              dmsg(7,("Condition::Waitif() -> waiting for 'true' condition with timeout\n"));
306              res = win32thread_cond_timedwait(&__win32_true_condition, &hMutex, &timeout);              res = ConditionInternal::win32thread_cond_timedwait(&__win32_true_condition, &hMutex, &timeout);
307              dmsg(7,("Condition::Waitif() -> awakened from 'true' condition waiting\n"));              dmsg(7,("Condition::Waitif() -> awakened from 'true' condition waiting\n"));
308              #else              #else
309              if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout              if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout

Legend:
Removed from v.1481  
changed lines
  Added in v.1560

  ViewVC Help
Powered by ViewVC