/[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 1480 by schoenebeck, Sun Oct 14 22:00:17 2007 UTC revision 1481 by senoner, Wed Nov 14 23:42:15 2007 UTC
# Line 27  Line 27 
27    
28  #include "global_private.h"  #include "global_private.h"
29    
30    #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  namespace LinuxSampler {  namespace LinuxSampler {
223    
224  Condition::Condition(bool bInitialCondition) {  Condition::Condition(bool bInitialCondition) {
225    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      pthread_cond_init(&__posix_true_condition, NULL);      pthread_cond_init(&__posix_true_condition, NULL);
231      pthread_cond_init(&__posix_false_condition, NULL);      pthread_cond_init(&__posix_false_condition, NULL);
232    #endif  
233      bCondition = bInitialCondition;      bCondition = bInitialCondition;
234  }  }
235    
236  Condition::~Condition() {  Condition::~Condition() {
237    #if defined(WIN32)
238        win32thread_cond_destroy(&__win32_true_condition);
239        win32thread_cond_destroy(&__win32_false_condition);
240    #else
241      pthread_cond_destroy(&__posix_true_condition);      pthread_cond_destroy(&__posix_true_condition);
242      pthread_cond_destroy(&__posix_false_condition);      pthread_cond_destroy(&__posix_false_condition);
243    #endif
244  }  }
245    
246  int Condition::WaitIf(bool bCondition, long TimeoutSeconds, long TimeoutNanoSeconds) {  int Condition::WaitIf(bool bCondition, long TimeoutSeconds, long TimeoutNanoSeconds) {
247        dmsg(7,("Condition::WaitIf: bCondition=%d  TimeoutSeconds=%d  TimeoutNanoSeconds=%d\n",bCondition, TimeoutSeconds, TimeoutNanoSeconds));
248      dmsg(7,("Condition::Waitif() -> LOCK()\n"));      dmsg(7,("Condition::Waitif() -> LOCK()\n"));
249      Lock();      Lock();
250      dmsg(7,("Condition::Waitif() -> LOCK() passed\n"));      dmsg(7,("Condition::Waitif() -> LOCK() passed\n"));
251      int res = 0;      int res = 0;
252      if (this->bCondition == bCondition) {      if (this->bCondition == bCondition) {
253          if (bCondition) { // wait until condition turned 'false'          if (bCondition) { // wait until condition turned 'false'
254                #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              if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout              if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout
263                  struct timeval now;                  struct timeval now;
264                  gettimeofday(&now, 0);                  gettimeofday(&now, 0);
# Line 62  int Condition::WaitIf(bool bCondition, l Line 274  int Condition::WaitIf(bool bCondition, l
274                  pthread_cond_wait(&__posix_false_condition, &__posix_mutex);                  pthread_cond_wait(&__posix_false_condition, &__posix_mutex);
275                  dmsg(7,("Condition::Waitif() -> awakened from 'false' condition waiting\n"));                  dmsg(7,("Condition::Waitif() -> awakened from 'false' condition waiting\n"));
276              }              }
277                #endif
278          }          }
279          else { // wait until condition turned 'true'          else { // wait until condition turned 'true'
280                #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              if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout              if (TimeoutSeconds || TimeoutNanoSeconds) { // wait with timeout
289                  struct timeval now;                  struct timeval now;
290                  gettimeofday(&now, 0);                  gettimeofday(&now, 0);
# Line 79  int Condition::WaitIf(bool bCondition, l Line 300  int Condition::WaitIf(bool bCondition, l
300                  pthread_cond_wait(&__posix_true_condition, &__posix_mutex);                  pthread_cond_wait(&__posix_true_condition, &__posix_mutex);
301                  dmsg(7,("Condition::Waitif() -> awakened from 'true' condition waiting\n"));                  dmsg(7,("Condition::Waitif() -> awakened from 'true' condition waiting\n"));
302              }              }
303                #endif
304          }          }
305      }      }
306      return res;      return res;
# Line 100  void Condition::Set(bool bCondition) { Line 322  void Condition::Set(bool bCondition) {
322          this->bCondition = bCondition;          this->bCondition = bCondition;
323          if (bCondition) {          if (bCondition) {
324              dmsg(7,("Condition::Set() -> broadcasting 'true' condition\n"));              dmsg(7,("Condition::Set() -> broadcasting 'true' condition\n"));
325                #if defined(WIN32)
326                win32thread_cond_broadcast(&__win32_true_condition);
327                #else
328              pthread_cond_broadcast(&__posix_true_condition);              pthread_cond_broadcast(&__posix_true_condition);
329                #endif
330          }          }
331          else {          else {
332              dmsg(7,("Condition::Set() -> broadcasting 'false' condition\n"));              dmsg(7,("Condition::Set() -> broadcasting 'false' condition\n"));
333                #if defined(WIN32)
334                win32thread_cond_broadcast(&__win32_false_condition);
335                #else
336              pthread_cond_broadcast(&__posix_false_condition);              pthread_cond_broadcast(&__posix_false_condition);
337                #endif
338          }          }
339      }      }
340      Unlock();      Unlock();

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

  ViewVC Help
Powered by ViewVC