+wxConditionInternal::wxConditionInternal()
+{
+ m_nQueuedSignals =
+ m_nWaiters = 0;
+
+ if ( pthread_cond_init(&m_condition, (pthread_condattr_t *)NULL) != 0 )
+ {
+ // this is supposed to never happen
+ wxFAIL_MSG( _T("pthread_cond_init() failed") );
+ }
+
+ if ( pthread_mutex_init(&m_mutex, NULL) != 0 )
+ {
+ // neither this
+ wxFAIL_MSG( _T("wxCondition: pthread_mutex_init() failed") );
+ }
+}
+
+wxConditionInternal::~wxConditionInternal()
+{
+ if ( pthread_cond_destroy( &m_condition ) != 0 )
+ {
+ wxLogDebug(_T("Failed to destroy condition variable (some "
+ "threads are probably still waiting on it?)"));
+ }
+
+ if ( pthread_mutex_destroy( &m_mutex ) != 0 )
+ {
+ wxLogDebug(_T("Failed to destroy mutex (it is probably locked)"));
+ }
+}
+
+bool wxConditionInternal::Wait(const timespec* ts)
+{
+ MutexLock lock(m_mutex);
+
+ if ( m_nQueuedSignals )
+ {
+ m_nQueuedSignals--;
+
+ wxLogTrace(TRACE_THREADS,
+ _T("wxCondition(%08x)::Wait(): Has been signaled before"),
+ this);
+
+ return TRUE;
+ }
+
+ // there are no queued signals, so start really waiting
+ m_nWaiters++;
+
+ // calling wait function below unlocks the mutex and Signal() or
+ // Broadcast() will be able to continue to run now if they were
+ // blocking for it in the loop locking all mutexes)
+ wxLogTrace(TRACE_THREADS,
+ _T("wxCondition(%08x)::Wait(): starting to wait"), this);
+
+ int err = ts ? pthread_cond_timedwait(&m_condition, &m_mutex, ts)
+ : pthread_cond_wait(&m_condition, &m_mutex);
+ switch ( err )
+ {
+ case 0:
+ // condition was signaled
+ wxLogTrace(TRACE_THREADS,
+ _T("wxCondition(%08x)::Wait(): ok"), this);
+ break;
+
+ default:
+ wxLogDebug(_T("unexpected pthread_cond_[timed]wait() return"));
+ // fall through
+
+ case ETIMEDOUT:
+ case EINTR:
+ // The condition has not been signaled, so we have to
+ // decrement the counter manually
+ --m_nWaiters;
+
+ // wait interrupted or timeout elapsed
+ wxLogTrace(TRACE_THREADS,
+ _T("wxCondition(%08x)::Wait(): timeout/intr"), this);
+ }
+
+ return err == 0;
+}
+
+void wxConditionInternal::Signal(bool all)
+{
+ // make sure that only one Signal() or Broadcast() is in progress
+ MutexLock lock(m_mutex);
+
+ // Are there any waiters?
+ if ( m_nWaiters == 0 )
+ {
+ // No, there are not, so don't signal but keep in mind for the next
+ // Wait()
+ m_nQueuedSignals++;
+
+ return;
+ }
+
+ // now we can finally signal it
+ wxLogTrace(TRACE_THREADS, _T("wxCondition(%08x)::Signal(): preparing to %s"),
+ this, all ? _T("broadcast") : _T("signal"));
+
+ int err = all ? pthread_cond_broadcast(&m_condition)
+ : pthread_cond_signal(&m_condition);
+
+ if ( all )
+ {
+ m_nWaiters = 0;
+ }
+ else
+ {
+ --m_nWaiters;
+ }
+
+ if ( err )
+ {
+ // shouldn't ever happen
+ wxFAIL_MSG(_T("pthread_cond_{broadcast|signal}() failed"));
+ }
+}
+
+// ----------------------------------------------------------------------------
+// wxCondition
+// ----------------------------------------------------------------------------
+