replaced ++/-- with InterlockedInc/Decrement for accessing global vars
also cleaned wxConditionInternal code a bit (more) git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@8639 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
bbee61e50e
commit
4d1c1c3c70
@ -211,44 +211,78 @@ class wxConditionInternal
|
|||||||
public:
|
public:
|
||||||
wxConditionInternal()
|
wxConditionInternal()
|
||||||
{
|
{
|
||||||
event = ::CreateEvent(
|
m_hEvent = ::CreateEvent(
|
||||||
NULL, // default secutiry
|
NULL, // default secutiry
|
||||||
FALSE, // not manual reset
|
FALSE, // not manual reset
|
||||||
FALSE, // nonsignaled initially
|
FALSE, // nonsignaled initially
|
||||||
NULL // nameless event
|
NULL // nameless event
|
||||||
);
|
);
|
||||||
if ( !event )
|
if ( !m_hEvent )
|
||||||
{
|
{
|
||||||
wxLogSysError(_("Can not create event object."));
|
wxLogSysError(_("Can not create event object."));
|
||||||
}
|
}
|
||||||
waiters = 0;
|
|
||||||
|
// nobody waits for us yet
|
||||||
|
m_nWaiters = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Wait(DWORD timeout)
|
bool Wait(DWORD timeout)
|
||||||
{
|
{
|
||||||
waiters++;
|
// as m_nWaiters variable is accessed from multiple waiting threads
|
||||||
|
// (and possibly from the broadcasting thread), we need to change its
|
||||||
|
// value atomically
|
||||||
|
::InterlockedIncrement(&m_nWaiters);
|
||||||
|
|
||||||
// FIXME this should be MsgWaitForMultipleObjects() as well probably
|
// FIXME this should be MsgWaitForMultipleObjects() as we want to keep
|
||||||
DWORD rc = ::WaitForSingleObject(event, timeout);
|
// processing Windows messages while waiting (or don't we?)
|
||||||
|
DWORD rc = ::WaitForSingleObject(m_hEvent, timeout);
|
||||||
|
|
||||||
waiters--;
|
::InterlockedDecrement(&m_nWaiters);
|
||||||
|
|
||||||
return rc != WAIT_TIMEOUT;
|
return rc != WAIT_TIMEOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Signal()
|
||||||
|
{
|
||||||
|
// set the event to signaled: if a thread is already waiting on it, it
|
||||||
|
// will be woken up, otherwise the event will remain in the signaled
|
||||||
|
// state until someone waits on it. In any case, the system will return
|
||||||
|
// it to a non signalled state afterwards. If multiple threads are
|
||||||
|
// waiting, only one will be woken up.
|
||||||
|
if ( !::SetEvent(m_hEvent) )
|
||||||
|
{
|
||||||
|
wxLogLastError(wxT("SetEvent"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Broadcast()
|
||||||
|
{
|
||||||
|
// this works because all these threads are already waiting and so each
|
||||||
|
// SetEvent() inside Signal() is really a PulseEvent() because the
|
||||||
|
// event state is immediately returned to non-signaled
|
||||||
|
for ( LONG n = 0; n < m_nWaiters; n++ )
|
||||||
|
{
|
||||||
|
Signal();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~wxConditionInternal()
|
~wxConditionInternal()
|
||||||
{
|
{
|
||||||
if ( event )
|
if ( m_hEvent )
|
||||||
{
|
{
|
||||||
if ( !::CloseHandle(event) )
|
if ( !::CloseHandle(m_hEvent) )
|
||||||
{
|
{
|
||||||
wxLogLastError(wxT("CloseHandle(event)"));
|
wxLogLastError(wxT("CloseHandle(event)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE event;
|
private:
|
||||||
int waiters;
|
// the Win32 synchronization object corresponding to this event
|
||||||
|
HANDLE m_hEvent;
|
||||||
|
|
||||||
|
// number of threads waiting for this condition
|
||||||
|
LONG m_nWaiters;
|
||||||
};
|
};
|
||||||
|
|
||||||
wxCondition::wxCondition()
|
wxCondition::wxCondition()
|
||||||
@ -274,26 +308,12 @@ bool wxCondition::Wait(unsigned long sec,
|
|||||||
|
|
||||||
void wxCondition::Signal()
|
void wxCondition::Signal()
|
||||||
{
|
{
|
||||||
// set the event to signaled: if a thread is already waiting on it, it will
|
m_internal->Signal();
|
||||||
// be woken up, otherwise the event will remain in the signaled state until
|
|
||||||
// someone waits on it. In any case, the system will return it to a non
|
|
||||||
// signalled state afterwards. If multiple threads are waiting, only one
|
|
||||||
// will be woken up.
|
|
||||||
if ( !::SetEvent(m_internal->event) )
|
|
||||||
{
|
|
||||||
wxLogLastError(wxT("SetEvent"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxCondition::Broadcast()
|
void wxCondition::Broadcast()
|
||||||
{
|
{
|
||||||
// this works because all these threads are already waiting and so each
|
m_internal->Broadcast();
|
||||||
// SetEvent() inside Signal() is really a PulseEvent() because the event
|
|
||||||
// state is immediately returned to non-signaled
|
|
||||||
for ( int i = 0; i < m_internal->waiters; i++ )
|
|
||||||
{
|
|
||||||
Signal();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
@ -1126,7 +1146,7 @@ void WXDLLEXPORT wxMutexGuiLeave()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// decrement the number of waiters now
|
// decrement the number of threads waiting for GUI access now
|
||||||
wxASSERT_MSG( gs_nWaitingForGui > 0,
|
wxASSERT_MSG( gs_nWaitingForGui > 0,
|
||||||
wxT("calling wxMutexGuiLeave() without entering it first?") );
|
wxT("calling wxMutexGuiLeave() without entering it first?") );
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user