Panda3D
 All Classes Functions Variables Enumerations
conditionVarFullWin32Impl.I
1 // Filename: conditionVarFullWin32Impl.I
2 // Created by: drose (28Aug06)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 
16 ////////////////////////////////////////////////////////////////////
17 // Function: ConditionVarFullWin32Impl::Constructor
18 // Access: Public
19 // Description:
20 ////////////////////////////////////////////////////////////////////
21 INLINE ConditionVarFullWin32Impl::
22 ConditionVarFullWin32Impl(MutexWin32Impl &mutex) {
23  _external_mutex = &mutex._lock;
24 
25  // Create an auto-reset event and a manual-reset event.
26  _event_signal = CreateEvent(NULL, false, false, NULL);
27  _event_broadcast = CreateEvent(NULL, true, false, NULL);
28 
29  _waiters_count = 0;
30 }
31 
32 ////////////////////////////////////////////////////////////////////
33 // Function: ConditionVarFullWin32Impl::Destructor
34 // Access: Public
35 // Description:
36 ////////////////////////////////////////////////////////////////////
37 INLINE ConditionVarFullWin32Impl::
38 ~ConditionVarFullWin32Impl() {
39  CloseHandle(_event_signal);
40  CloseHandle(_event_broadcast);
41 }
42 
43 ////////////////////////////////////////////////////////////////////
44 // Function: ConditionVarFullWin32Impl::wait
45 // Access: Public
46 // Description:
47 ////////////////////////////////////////////////////////////////////
48 INLINE void ConditionVarFullWin32Impl::
49 wait() {
50  AtomicAdjust::inc(_waiters_count);
51 
52  // It's ok to release the external_mutex here since Win32
53  // manual-reset events maintain state when used with SetEvent().
54  // This avoids the "lost wakeup" bug...
55  LeaveCriticalSection(_external_mutex);
56 
57  // Wait for either event to become signaled due to notify() being
58  // called or notify_all() being called.
59  int result = WaitForMultipleObjects(2, &_event_signal, FALSE, INFINITE);
60 
61  bool nonzero = AtomicAdjust::dec(_waiters_count);
62  bool last_waiter = (result == WAIT_OBJECT_0 + 1 && !nonzero);
63 
64  // Some thread called notify_all().
65  if (last_waiter) {
66  // We're the last waiter to be notified or to stop waiting, so
67  // reset the manual event.
68  ResetEvent(_event_broadcast);
69  }
70 
71  // Reacquire the <external_mutex>.
72  EnterCriticalSection(_external_mutex);
73 }
74 
75 ////////////////////////////////////////////////////////////////////
76 // Function: ConditionVarFullWin32Impl::wait
77 // Access: Public
78 // Description:
79 ////////////////////////////////////////////////////////////////////
80 INLINE void ConditionVarFullWin32Impl::
81 wait(double timeout) {
82  AtomicAdjust::inc(_waiters_count);
83 
84  // It's ok to release the external_mutex here since Win32
85  // manual-reset events maintain state when used with SetEvent().
86  // This avoids the "lost wakeup" bug...
87  LeaveCriticalSection(_external_mutex);
88 
89  // Wait for either event to become signaled due to notify() being
90  // called or notify_all() being called.
91  int result = WaitForMultipleObjects(2, &_event_signal, FALSE, (DWORD)(timeout * 1000.0));
92 
93  bool nonzero = AtomicAdjust::dec(_waiters_count);
94  bool last_waiter = (result == WAIT_OBJECT_0 + 1 && !nonzero);
95 
96  // Some thread called notify_all().
97  if (last_waiter) {
98  // We're the last waiter to be notified or to stop waiting, so
99  // reset the manual event.
100  ResetEvent(_event_broadcast);
101  }
102 
103  // Reacquire the <external_mutex>.
104  EnterCriticalSection(_external_mutex);
105 }
106 
107 ////////////////////////////////////////////////////////////////////
108 // Function: ConditionVarFullWin32Impl::notify
109 // Access: Public
110 // Description:
111 ////////////////////////////////////////////////////////////////////
112 INLINE void ConditionVarFullWin32Impl::
113 notify() {
114  bool have_waiters = AtomicAdjust::get(_waiters_count) > 0;
115 
116  if (have_waiters) {
117  SetEvent(_event_signal);
118  }
119 }
120 
121 ////////////////////////////////////////////////////////////////////
122 // Function: ConditionVarFullWin32Impl::notify_all
123 // Access: Public
124 // Description:
125 ////////////////////////////////////////////////////////////////////
126 INLINE void ConditionVarFullWin32Impl::
127 notify_all() {
128  bool have_waiters = AtomicAdjust::get(_waiters_count) > 0;
129 
130  if (have_waiters) {
131  SetEvent(_event_broadcast);
132  }
133 }
static void inc(Integer &var)
Atomically increments the indicated variable.
static bool dec(Integer &var)
Atomically decrements the indicated variable and returns true if the new value is nonzero...
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.