Panda3D
Loading...
Searching...
No Matches
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 */
17INLINE ConditionVarFullWin32Impl::
18ConditionVarFullWin32Impl(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 */
31INLINE ConditionVarFullWin32Impl::
32~ConditionVarFullWin32Impl() {
33 CloseHandle(_event_signal);
34 CloseHandle(_event_broadcast);
35}
36
37/**
38 *
39 */
40INLINE void ConditionVarFullWin32Impl::
41wait() {
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 */
70INLINE void ConditionVarFullWin32Impl::
71wait(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 */
100INLINE void ConditionVarFullWin32Impl::
101notify() {
102 bool have_waiters = AtomicAdjust::get(_waiters_count) > 0;
103
104 if (have_waiters) {
105 SetEvent(_event_signal);
106 }
107}
108
109/**
110 *
111 */
112INLINE void ConditionVarFullWin32Impl::
113notify_all() {
114 bool have_waiters = AtomicAdjust::get(_waiters_count) > 0;
115
116 if (have_waiters) {
117 SetEvent(_event_broadcast);
118 }
119}
static bool dec(Integer &var)
Atomically decrements the indicated variable and returns true if the new value is nonzero,...
static void inc(Integer &var)
Atomically increments the indicated variable.
static Integer get(const Integer &var)
Atomically retrieves the snapshot value of the indicated variable.