KWStyle - itkConditionVariable.cxx
 
Matrix View
Description

1 /*=========================================================================
2
3   Program:   Insight Segmentation & Registration Toolkit
4   Module:    $RCSfile: itkConditionVariable.cxx.html,v $
5   Language:  C++
6   Date:      $Date: 2006/01/17 19:15:34 $
7   Version:   $Revision: 1.4 $
8
9   Copyright (c) Insight Software Consortium. All rights reserved.
10   See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
11
12      This software is distributed WITHOUT ANY WARRANTY; without even 
13      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14      PURPOSE.  See the above copyright notices for more information.
15
16 =========================================================================*/
17 DEF #ifndef  _itkConditionVariable_cxx_
18 DEF #define  _itkConditionVariable_cxx_
19
20 #include "itkConditionVariable.h"
21
22 namespace itk {
23   
24 ConditionVariable::ConditionVariable()
25 {
26 #ifdef ITK_USE_PTHREADS
27   pthread_mutex_init(&m_Mutex, NULL);
28   pthread_cond_init(&m_ConditionVariable, NULL);
29 IND #else
30 #ifdef WIN32
31   m_NumberOfWaiters = 0;
32   m_WasBroadcast = 0;
33   m_Semaphore = CreateSemaphore(NULL,         // no security
34                                 0,            // initial value
35                                 0x7fffffff,   // max count
36                                 NULL);        // unnamed
37   InitializeCriticalSection( &m_NumberOfWaitersLock );
38   m_WaitersAreDone = CreateEvent( NULL,           // no security
39                                   FALSE,          // auto-reset
40                                   FALSE,          // non-signaled initially
41                                   NULL );         // unnamed
42 #endif
43 #endif
44 }
45
46 ConditionVariable::~ConditionVariable()
47 {
48 #ifdef ITK_USE_PTHREADS
49   pthread_mutex_destroy(&m_Mutex);
50   pthread_cond_destroy(&m_ConditionVariable);
51 IND #else
52 #ifdef WIN32
53   CloseHandle( m_Semaphore );
54   CloseHandle( m_WaitersAreDone );
55   DeleteCriticalSection( &m_NumberOfWaitersLock );
56 #endif
57 #endif
58   
59 }
60
61 void ConditionVariable::Signal()  
62 {
63 #ifdef ITK_USE_PTHREADS
64   pthread_cond_signal(&m_ConditionVariable);
65 IND #else
66 #ifdef WIN32
67   EnterCriticalSection( &m_NumberOfWaitersLock );
68   int haveWaiters = m_NumberOfWaiters > 0;
69   LeaveCriticalSection( &m_NumberOfWaitersLock );
70
71   // if there were not any waiters, then this is a no-op
72   if (haveWaiters)
73     {
74     ReleaseSemaphore(m_Semaphore, 1, 0);
75     }
76 #endif
77 #endif
78 }
79
80 void ConditionVariable::Broadcast()
81 {
82 #ifdef ITK_USE_PTHREADS
83   pthread_cond_broadcast(&m_ConditionVariable);
84 IND #else
85 #ifdef WIN32
86   // This is needed to ensure that m_NumberOfWaiters and m_WasBroadcast are
87   // consistent
88   EnterCriticalSection( &m_NumberOfWaitersLock );
89   int haveWaiters = 0;
90
91   if (m_NumberOfWaiters > 0)
92     {
93     // We are broadcasting, even if there is just one waiter...
94     // Record that we are broadcasting, which helps optimize Wait()
95     // for the non-broadcast case
96     m_WasBroadcast = 1;
97     haveWaiters = 1;
98     }
99
100   if (haveWaiters)
101     {
102     // Wake up all waiters atomically
103     ReleaseSemaphore(m_Semaphore, m_NumberOfWaiters, 0);
104
105     LeaveCriticalSection( &m_NumberOfWaitersLock );
106
107     // Wait for all the awakened threads to acquire the counting
108     // semaphore
109     WaitForSingleObject( m_WaitersAreDone, INFINITE );
110     // This assignment is ok, even without the m_NumberOfWaitersLock held
111     // because no other waiter threads can wake up to access it.
112     m_WasBroadcast = 0;
113     }
114   else
115     {
116     LeaveCriticalSection( &m_NumberOfWaitersLock );
117     }
118 #endif
119 #endif
120 }
121
122 void ConditionVariable::Wait(SimpleMutexLock *mutex)
123 {
124 #ifdef ITK_USE_PTHREADS
125   pthread_cond_wait(&m_ConditionVariable, &mutex->GetMutexLock() );
126 IND #else
127 #ifdef WIN32
128   // Avoid race conditions
129   EnterCriticalSection( &m_NumberOfWaitersLock );
130   m_NumberOfWaiters++;
131   LeaveCriticalSection( &m_NumberOfWaitersLock );
132
133   // This call atomically releases the mutex and waits on the
134   // semaphore until signaled
135   SignalObjectAndWait( mutex->GetMutexLock(), m_Semaphore, INFINITE, FALSE );
136
137   // Reacquire lock to avoid race conditions
138   EnterCriticalSection( &m_NumberOfWaitersLock );
139
140   // We're no longer waiting....
141   m_NumberOfWaiters--;
142
143   // Check to see if we're the last waiter after the broadcast
144   int lastWaiter = m_WasBroadcast && m_NumberOfWaiters == 0;
145
146   LeaveCriticalSection( &m_NumberOfWaitersLock );
147
148   // If we're the last waiter thread during this particular broadcast
149   // then let the other threads proceed
150   if (lastWaiter)
151     {
152     // This call atomically signals the m_WaitersAreDone event and waits
153     // until it can acquire the external mutex.  This is required to
154     // ensure fairness
155 LEN     SignalObjectAndWait( m_WaitersAreDone, mutex->GetMutexLock(), INFINITE, FALSE);
156     }
157   else
158     {
159     // Always regain the external mutex since that's the guarentee we
160     // give to our callers
161     WaitForSingleObject( mutex->GetMutexLock(), INFINITE );
162     }
163 #endif
164 #endif
165 }
166
167 }//end of namespace itk
168
169 #endif
170

Generated by KWStyle 1.0b on Tuesday January,17 at 02:14:03PM
© Kitware Inc.