After signalling an event, always wait for the signalled thread to touch

m_WaitersDone.  This fixes problems with

 event.Lock();
 event.Signal();
 while(x) event.Wait();

picking up the signal that it just sent (which is wrong), especially in the
debugger.
This commit is contained in:
Glenn Maynard
2005-01-27 01:19:24 +00:00
parent 582a2ec27a
commit 903aaadcc5
2 changed files with 9 additions and 13 deletions
+9 -12
View File
@@ -259,7 +259,6 @@ EventImpl_Win32::EventImpl_Win32( MutexImpl_Win32 *pParent )
{
m_pParent = pParent;
m_iNumWaiting = 0;
m_bNeedSignal = false;
m_WakeupSema = CreateSemaphore( NULL, 0, 0x7fffffff, NULL );
InitializeCriticalSection( &m_iNumWaitingLock );
m_WaitersDone = CreateEvent( NULL, FALSE, FALSE, NULL );
@@ -334,11 +333,10 @@ bool EventImpl_Win32::Wait( RageTimer *pTimeout )
EnterCriticalSection( &m_iNumWaitingLock );
--m_iNumWaiting;
bool bLastWaiting = m_bNeedSignal && m_iNumWaiting == 0;
bool bLastWaiting = m_iNumWaiting == 0;
LeaveCriticalSection( &m_iNumWaitingLock );
/* If m_bNeedSignal is set, and we're the last waiter to wake up, signal the
* broadcaster. */
/* If we're the last waiter to wake up, wake up the signaller. */
if( bLastWaiting )
PortableSignalObjectAndWait( m_WaitersDone, m_pParent->mutex, false );
else
@@ -354,7 +352,12 @@ void EventImpl_Win32::Signal()
LeaveCriticalSection( &m_iNumWaitingLock );
if( bHaveWaiters )
{
ReleaseSemaphore( m_WakeupSema, 1, 0 );
/* The waiter will touch m_WaitersDone. */
WaitForSingleObject( m_WaitersDone, INFINITE );
}
}
void EventImpl_Win32::Broadcast()
@@ -367,19 +370,13 @@ void EventImpl_Win32::Broadcast()
return;
}
/* Since we're broadcasting, we need to wait for all waiters to wake up and
* start waiting for the mutex before returning. */
m_bNeedSignal = true;
ReleaseSemaphore( m_WakeupSema, m_iNumWaiting, 0 );
LeaveCriticalSection( &m_iNumWaitingLock );
/* We set m_bNeedSignal; the last waiter will touch m_WaitersDone. Note that
* we still hold the parent mutex, so no other thread is currently broadcasting;
* we don't have to worry about m_bNeedSignal being set to false on us. */
/* The last waiter will touch m_WaitersDone, so we wait for all waiters to wake up and
* start waiting for the mutex before returning. */
WaitForSingleObject( m_WaitersDone, INFINITE );
m_bNeedSignal = false;
}
EventImpl *MakeEvent( MutexImpl *pMutex )
@@ -57,7 +57,6 @@ private:
CRITICAL_SECTION m_iNumWaitingLock;
HANDLE m_WakeupSema;
HANDLE m_WaitersDone;
bool m_bNeedSignal;
};
class SemaImpl_Win32: public SemaImpl