+wxCondError wxConditionInternal::WaitTimeout(unsigned long msectimeout)
+{
+ m_gate.Wait();
+ if ( ++ m_waiters == INT_MAX)
+ {
+ m_varSection.Enter();
+ m_waiters -= m_canceled;
+ m_signals -= m_canceled;
+ m_canceled = 0;
+ m_varSection.Leave();
+ }
+ m_gate.Post();
+
+ m_mutex.Unlock();
+
+ wxSemaError err = m_semaphore.WaitTimeout( msectimeout);
+ wxASSERT( err == wxSEMA_NO_ERROR || err == wxSEMA_TIMEOUT);
+
+ m_varSection.Enter();
+ if ( err != wxSEMA_NO_ERROR)
+ {
+ if ( m_signals > m_canceled)
+ {
+ // A signal is being sent after we timed out.
+
+ if ( m_waiters == m_signals)
+ {
+ // There are no excess waiters to catch the signal, so
+ // we must throw it away.
+
+ wxSemaError err2 = m_semaphore.Wait();
+ if ( err2 != wxSEMA_NO_ERROR)
+ {
+ wxLogSysError(_("Error while waiting on semaphore"));
+ }
+ wxASSERT( err2 == wxSEMA_NO_ERROR);
+ -- m_waiters;
+ if ( -- m_signals == m_canceled)
+ {
+ // This was the last signal. open the gate.
+ wxASSERT( m_waiters == m_canceled);
+ m_gate.Post();
+ }
+ }
+ else
+ {
+ // There are excess waiters to catch the signal, leave
+ // it be.
+ -- m_waiters;
+ }
+ }
+ else
+ {
+ // No signals is being sent.
+ // The gate may be open or closed, so we can't touch m_waiters.
+ ++ m_canceled;
+ ++ m_signals;
+ }
+ }
+ else
+ {
+ // We caught a signal.
+ wxASSERT( m_signals > m_canceled);
+ -- m_waiters;
+ if ( -- m_signals == m_canceled)
+ {
+ // This was the last signal. open the gate.
+ wxASSERT( m_waiters == m_canceled);
+ m_gate.Post();
+ }
+ }
+ m_varSection.Leave();
+
+ m_mutex.Lock();
+
+ if ( err)
+ {
+ return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
+ }
+
+ return wxCOND_NO_ERROR;
+}
+
+
+wxCondError wxConditionInternal::DoSignal( bool signalAll)
+{
+ m_gate.Wait();
+ m_varSection.Enter();
+
+ wxASSERT( m_signals == m_canceled);
+
+ if ( m_waiters == m_canceled)
+ {
+ m_varSection.Leave();
+ m_gate.Post();
+ return wxCOND_NO_ERROR;
+ }
+
+ if ( m_canceled > 0)
+ {
+ m_waiters -= m_canceled;
+ m_signals = 0;
+ m_canceled = 0;
+ }
+
+ m_signals = signalAll ? m_waiters : 1;
+ size_t n = m_signals;
+
+ m_varSection.Leave();
+
+ // Let the waiters inherit the gate lock.
+
+ do
+ {
+ wxSemaError err = m_semaphore.Post();
+ wxASSERT( err == wxSEMA_NO_ERROR);
+ } while ( -- n);
+
+ return wxCOND_NO_ERROR;
+}
+
+#else
+class wxConditionInternal
+{
+public:
+ wxConditionInternal(wxMutex& mutex);
+
+ bool IsOk() const { return m_mutex.IsOk() && m_semaphore.IsOk(); }
+
+ wxCondError Wait();
+ wxCondError WaitTimeout(unsigned long milliseconds);
+
+ wxCondError Signal();
+ wxCondError Broadcast();