Panda3D

conditionVarFullWin32Impl.I

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 }
 All Classes Functions Variables Enumerations