+wxConditionInternal::wxConditionInternal()
+{
+ m_wasSignaled = FALSE;
+ 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, (pthread_mutexattr_t *)NULL) != 0 ||
+ pthread_mutex_init(&m_mutexProtect, NULL) != 0 )
+ {
+ // neither this
+ wxFAIL_MSG( _T("wxCondition: pthread_mutex_init() failed") );
+ }
+
+ // initially the mutex is locked, so no thread can Signal() or Broadcast()
+ // until another thread starts to Wait()
+ if ( pthread_mutex_lock(&m_mutex) != 0 )
+ {
+ wxFAIL_MSG( _T("wxCondition: pthread_mutex_lock() 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_unlock( &m_mutex ) != 0 )
+ {
+ wxLogDebug(_T("wxCondition: failed to unlock the mutex"));
+ }
+
+ if ( pthread_mutex_destroy( &m_mutex ) != 0 ||
+ pthread_mutex_destroy( &m_mutexProtect ) != 0 )
+ {
+ wxLogDebug(_T("Failed to destroy mutex (it is probably locked)"));
+ }
+}
+
+void wxConditionInternal::WaitDone()
+{
+ MutexLock lock(m_mutexProtect);
+
+ m_wasSignaled = FALSE;
+ m_nWaiters--;
+}
+
+bool wxConditionInternal::ShouldWait()
+{
+ MutexLock lock(m_mutexProtect);
+
+ if ( m_wasSignaled )
+ {
+ // the condition was signaled before we started to wait, reset the
+ // flag and return
+ m_wasSignaled = FALSE;
+
+ return FALSE;
+ }
+
+ // we start to wait for it
+ m_nWaiters++;
+
+ return TRUE;
+}
+
+bool wxConditionInternal::HasWaiters()
+{
+ MutexLock lock(m_mutexProtect);
+
+ if ( m_nWaiters )
+ {
+ // someone waits for us, signal the condition normally
+ return TRUE;
+ }
+
+ // nobody waits for us and may be never will - so just remember that the
+ // condition was signaled and don't do anything else
+ m_wasSignaled = TRUE;
+
+ return FALSE;
+}
+
+void wxConditionInternal::Wait()
+{
+ if ( ShouldWait() )
+ {
+ if ( pthread_cond_wait( &m_condition, &m_mutex ) != 0 )
+ {
+ // not supposed to ever happen
+ wxFAIL_MSG( _T("pthread_cond_wait() failed") );
+ }
+ }
+
+ WaitDone();
+}
+
+bool wxConditionInternal::WaitWithTimeout(const timespec* ts)
+{
+ bool ok;
+
+ if ( ShouldWait() )
+ {
+ switch ( pthread_cond_timedwait( &m_condition, &m_mutex, ts ) )
+ {
+ case 0:
+ // condition signaled
+ ok = TRUE;
+ break;
+
+ default:
+ wxLogDebug(_T("pthread_cond_timedwait() failed"));
+
+ // fall through
+
+ case ETIMEDOUT:
+ case EINTR:
+ // wait interrupted or timeout elapsed
+ ok = FALSE;
+ }
+ }
+ else
+ {
+ // the condition had already been signaled before
+ ok = TRUE;
+ }
+
+ WaitDone();
+
+ return ok;
+}
+
+void wxConditionInternal::Signal()
+{
+ if ( HasWaiters() )
+ {
+ MutexLock lock(m_mutex);
+
+ if ( pthread_cond_signal( &m_condition ) != 0 )
+ {
+ // shouldn't ever happen
+ wxFAIL_MSG(_T("pthread_cond_signal() failed"));
+ }
+ }
+}
+
+void wxConditionInternal::Broadcast()
+{
+ if ( HasWaiters() )
+ {
+ MutexLock lock(m_mutex);
+
+ if ( pthread_cond_broadcast( &m_condition ) != 0 )
+ {
+ // shouldn't ever happen
+ wxFAIL_MSG(_T("pthread_cond_broadcast() failed"));
+ }
+ }
+}
+