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