00001 // Filename: conditionVarFullWin32Impl.I 00002 // Created by: drose (28Aug06) 00003 // 00004 //////////////////////////////////////////////////////////////////// 00005 // 00006 // PANDA 3D SOFTWARE 00007 // Copyright (c) Carnegie Mellon University. All rights reserved. 00008 // 00009 // All use of this software is subject to the terms of the revised BSD 00010 // license. You should have received a copy of this license along 00011 // with this source code in a file named "LICENSE." 00012 // 00013 //////////////////////////////////////////////////////////////////// 00014 00015 00016 //////////////////////////////////////////////////////////////////// 00017 // Function: ConditionVarFullWin32Impl::Constructor 00018 // Access: Public 00019 // Description: 00020 //////////////////////////////////////////////////////////////////// 00021 INLINE ConditionVarFullWin32Impl:: 00022 ConditionVarFullWin32Impl(MutexWin32Impl &mutex) { 00023 _external_mutex = &mutex._lock; 00024 00025 // Create an auto-reset event and a manual-reset event. 00026 _event_signal = CreateEvent(NULL, false, false, NULL); 00027 _event_broadcast = CreateEvent(NULL, true, false, NULL); 00028 00029 _waiters_count = 0; 00030 } 00031 00032 //////////////////////////////////////////////////////////////////// 00033 // Function: ConditionVarFullWin32Impl::Destructor 00034 // Access: Public 00035 // Description: 00036 //////////////////////////////////////////////////////////////////// 00037 INLINE ConditionVarFullWin32Impl:: 00038 ~ConditionVarFullWin32Impl() { 00039 CloseHandle(_event_signal); 00040 CloseHandle(_event_broadcast); 00041 } 00042 00043 //////////////////////////////////////////////////////////////////// 00044 // Function: ConditionVarFullWin32Impl::wait 00045 // Access: Public 00046 // Description: 00047 //////////////////////////////////////////////////////////////////// 00048 INLINE void ConditionVarFullWin32Impl:: 00049 wait() { 00050 AtomicAdjust::inc(_waiters_count); 00051 00052 // It's ok to release the external_mutex here since Win32 00053 // manual-reset events maintain state when used with SetEvent(). 00054 // This avoids the "lost wakeup" bug... 00055 LeaveCriticalSection(_external_mutex); 00056 00057 // Wait for either event to become signaled due to notify() being 00058 // called or notify_all() being called. 00059 int result = WaitForMultipleObjects(2, &_event_signal, FALSE, INFINITE); 00060 00061 bool nonzero = AtomicAdjust::dec(_waiters_count); 00062 bool last_waiter = (result == WAIT_OBJECT_0 + 1 && !nonzero); 00063 00064 // Some thread called notify_all(). 00065 if (last_waiter) { 00066 // We're the last waiter to be notified or to stop waiting, so 00067 // reset the manual event. 00068 ResetEvent(_event_broadcast); 00069 } 00070 00071 // Reacquire the <external_mutex>. 00072 EnterCriticalSection(_external_mutex); 00073 } 00074 00075 //////////////////////////////////////////////////////////////////// 00076 // Function: ConditionVarFullWin32Impl::wait 00077 // Access: Public 00078 // Description: 00079 //////////////////////////////////////////////////////////////////// 00080 INLINE void ConditionVarFullWin32Impl:: 00081 wait(double timeout) { 00082 AtomicAdjust::inc(_waiters_count); 00083 00084 // It's ok to release the external_mutex here since Win32 00085 // manual-reset events maintain state when used with SetEvent(). 00086 // This avoids the "lost wakeup" bug... 00087 LeaveCriticalSection(_external_mutex); 00088 00089 // Wait for either event to become signaled due to notify() being 00090 // called or notify_all() being called. 00091 int result = WaitForMultipleObjects(2, &_event_signal, FALSE, (DWORD)(timeout * 1000.0)); 00092 00093 bool nonzero = AtomicAdjust::dec(_waiters_count); 00094 bool last_waiter = (result == WAIT_OBJECT_0 + 1 && !nonzero); 00095 00096 // Some thread called notify_all(). 00097 if (last_waiter) { 00098 // We're the last waiter to be notified or to stop waiting, so 00099 // reset the manual event. 00100 ResetEvent(_event_broadcast); 00101 } 00102 00103 // Reacquire the <external_mutex>. 00104 EnterCriticalSection(_external_mutex); 00105 } 00106 00107 //////////////////////////////////////////////////////////////////// 00108 // Function: ConditionVarFullWin32Impl::notify 00109 // Access: Public 00110 // Description: 00111 //////////////////////////////////////////////////////////////////// 00112 INLINE void ConditionVarFullWin32Impl:: 00113 notify() { 00114 bool have_waiters = AtomicAdjust::get(_waiters_count) > 0; 00115 00116 if (have_waiters) { 00117 SetEvent(_event_signal); 00118 } 00119 } 00120 00121 //////////////////////////////////////////////////////////////////// 00122 // Function: ConditionVarFullWin32Impl::notify_all 00123 // Access: Public 00124 // Description: 00125 //////////////////////////////////////////////////////////////////// 00126 INLINE void ConditionVarFullWin32Impl:: 00127 notify_all() { 00128 bool have_waiters = AtomicAdjust::get(_waiters_count) > 0; 00129 00130 if (have_waiters) { 00131 SetEvent(_event_broadcast); 00132 } 00133 }