Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TWin32Condition.cxx
Go to the documentation of this file.
1// @(#)root/thread:$Id$
2// Author: Bertrand Bellenot 20/10/2004
3
4/*************************************************************************
5 * Copyright (C) 1995-2004, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12//////////////////////////////////////////////////////////////////////////
13// //
14// TWin32Condition //
15// //
16// This class provides an interface to the win32 condition variable //
17// routines. //
18// //
19//////////////////////////////////////////////////////////////////////////
20
21#include "TWin32Condition.h"
22#include "TWin32Mutex.h"
23#include "TTimeStamp.h"
24#include "Windows4Root.h"
25
26#include <cerrno>
27
28
29////////////////////////////////////////////////////////////////////////////////
30/// Create Condition variable. Ctor must be given a pointer to an
31/// existing mutex. The condition variable is then linked to the mutex,
32/// so that there is an implicit unlock and lock around Wait() and
33/// TimedWait().
34
36{
37 fMutex = (TWin32Mutex *) m;
38
41 fCond.sema_ = CreateSemaphore(0, // no security
42 0, // initially 0
43 0x7fffffff, // max count
44 0); // unnamed
46 fCond.waiters_done_ = CreateEvent(0, // no security
47 FALSE, // auto-reset
48 FALSE, // non-signaled initially
49 0); // unnamed
50}
51
52////////////////////////////////////////////////////////////////////////////////
53/// TCondition dtor.
54
58
59////////////////////////////////////////////////////////////////////////////////
60/// Wait for the condition variable to be signalled. The mutex is
61/// implicitely released before waiting and locked again after waking up.
62/// If Wait() is called by multiple threads, a signal may wake up more
63/// than one thread. See POSIX threads documentation for details.
64
66{
67 // Avoid race conditions.
71
72 // This call atomically releases the mutex and waits on the
73 // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
74 // are called by another thread.
75 // SignalObjectAndWait(fMutex->fHMutex, fCond.sema_, INFINITE, FALSE);
78
79 // Reacquire lock to avoid race conditions.
81
82 // We're no longer waiting...
84
85 // Check to see if we're the last waiter after <pthread_cond_broadcast>.
87
89
90 // If we're the last waiter thread during this particular broadcast
91 // then let all the other threads proceed.
92 if (last_waiter) {
93 // This call atomically signals the <waiters_done_> event and waits until
94 // it can acquire the <fMutex->fHMutex>. This is required to ensure fairness.
95 // SignalObjectAndWait(fCond.waiters_done_, fMutex->fHMutex, INFINITE, FALSE);
96 SetEvent(fCond.waiters_done_);
98 }
99 else
100 // Always regain the external mutex since that's the guarantee we
101 // give to our callers.
102 // WaitForSingleObject(fMutex->fHMutex, INFINITE);
104
105 return 0;
106}
107
108////////////////////////////////////////////////////////////////////////////////
109/// TimedWait() is given an absolute time to wait until. To wait for a
110/// relative time from now, use TThread::GetTime(). See POSIX threads
111/// documentation for why absolute times are better than relative.
112/// Returns 0 if successfully signalled, 1 if time expired.
113
115{
116 DWORD ret;
117 TTimeStamp t;
118 // Get actual time
119 ULong_t secNow = t.GetSec();
121 DWORD dwMillisecondsNow = (DWORD)((secNow * 1000) + (nanosecNow / 1000000));
122 DWORD dwMilliseconds = (DWORD)((secs * 1000) + (nanoSecs / 1000000));
123 // Calculate delta T to obtain the real time to wait for
125 // Avoid race conditions.
129
130 // This call atomically releases the mutex and waits on the
131 // semaphore until <pthread_cond_signal> or <pthread_cond_broadcast>
132 // are called by another thread.
133 // ret = SignalObjectAndWait(fMutex->fHMutex, fCond.sema_, dwTimeWait, FALSE);
136
137 // Reacquire lock to avoid race conditions.
139
140 // We're no longer waiting...
142
143 // Check to see if we're the last waiter after <pthread_cond_broadcast>.
145
147
148 // If we're the last waiter thread during this particular broadcast
149 // then let all the other threads proceed.
150 if (last_waiter) {
151 // This call atomically signals the <waiters_done_> event and waits until
152 // it can acquire the <fMutex->fHMutex>. This is required to ensure fairness.
153 // SignalObjectAndWait(fCond.waiters_done_, fMutex->fHMutex, dwTimeWait, FALSE);
154 SetEvent(fCond.waiters_done_);
156 }
157 else
158 // Always regain the external mutex since that's the guarantee we
159 // give to our callers.
160 // WaitForSingleObject(fMutex->fHMutex, INFINITE);
162
163 if (ret == WAIT_TIMEOUT)
164 return 1;
165 return 0;
166}
167
168////////////////////////////////////////////////////////////////////////////////
169/// If one or more threads have called Wait(), Signal() wakes up at least
170/// one of them, possibly more. See POSIX threads documentation for details.
171
173{
177
178 // If there aren't any waiters, then this is a no-op.
179 if (have_waiters)
180 ReleaseSemaphore(fCond.sema_, 1, 0);
181
182 return 0;
183}
184
185
186////////////////////////////////////////////////////////////////////////////////
187/// Broadcast is like signal but wakes all threads which have called Wait().
188
190{
191 // This is needed to ensure that <waiters_count_> and <was_broadcast_> are
192 // consistent relative to each other.
194 int have_waiters = 0;
195
196 if (fCond.waiters_count_ > 0) {
197 // We are broadcasting, even if there is just one waiter...
198 // Record that we are broadcasting, which helps optimize
199 // <pthread_cond_wait> for the non-broadcast case.
201 have_waiters = 1;
202 }
203
204 if (have_waiters) {
205 // Wake up all the waiters atomically.
206 ReleaseSemaphore(fCond.sema_, fCond.waiters_count_, 0);
207
209
210 // Wait for all the awakened threads to acquire the counting
211 // semaphore.
213 // This assignment is okay, even without the <waiters_count_lock_> held
214 // because no other waiter threads can wake up to access it.
216 }
217 else
219
220 return 0;
221}
unsigned long ULong_t
Unsigned long integer 4 bytes (unsigned long). Size depends on architecture.
Definition RtypesCore.h:69
ROOT::Detail::TRangeCast< T, true > TRangeDynCast
TRangeDynCast is an adapter class that allows the typed iteration through a TCollection.
The TTimeStamp encapsulates seconds and ns since EPOCH.
Definition TTimeStamp.h:45
time_t GetSec() const
Definition TTimeStamp.h:109
Int_t GetNanoSec() const
Definition TTimeStamp.h:110
Int_t TimedWait(ULong_t secs, ULong_t nanoSecs=0) override
TimedWait() is given an absolute time to wait until.
Int_t Signal() override
If one or more threads have called Wait(), Signal() wakes up at least one of them,...
pthread_cond_t fCond
virtual ~TWin32Condition()
TCondition dtor.
TWin32Condition(TMutexImp *m)
Create Condition variable.
Int_t Broadcast() override
Broadcast is like signal but wakes all threads which have called Wait().
TWin32Mutex * fMutex
Int_t Wait() override
Wait for the condition variable to be signalled.
CRITICAL_SECTION fCritSect
Definition TWin32Mutex.h:33
CRITICAL_SECTION waiters_count_lock_
TMarker m
Definition textangle.C:8