+ wxCHECK_MSG( m_isOk , wxMUTEX_MISC_ERROR , wxT("Invalid Mutex") ) ;
+
+ OSStatus err = MPExitCriticalRegion( m_critRegion );
+ MPYield() ;
+
+ if (err != noErr)
+ {
+ wxLogSysError( wxT("Could not unlock mutex") );
+
+ return wxMUTEX_MISC_ERROR;
+ }
+
+ return wxMUTEX_NO_ERROR;
+}
+
+#endif
+
+// --------------------------------------------------------------------------
+// wxSemaphore
+// --------------------------------------------------------------------------
+
+class wxSemaphoreInternal
+{
+public:
+ wxSemaphoreInternal( int initialcount, int maxcount );
+ virtual ~wxSemaphoreInternal();
+
+ bool IsOk() const
+ { return m_isOk; }
+
+ wxSemaError Post();
+ wxSemaError WaitTimeout( unsigned long milliseconds );
+
+ wxSemaError Wait()
+ { return WaitTimeout( kDurationForever); }
+
+ wxSemaError TryWait()
+ {
+ wxSemaError err = WaitTimeout( kDurationImmediate );
+ if (err == wxSEMA_TIMEOUT)
+ err = wxSEMA_BUSY;
+
+ return err;
+ }
+
+private:
+ MPSemaphoreID m_semaphore;
+ bool m_isOk;
+};
+
+wxSemaphoreInternal::wxSemaphoreInternal( int initialcount, int maxcount)
+{
+ m_isOk = false;
+ m_semaphore = kInvalidID;
+ if ( maxcount == 0 )
+ // make it practically infinite
+ maxcount = INT_MAX;
+
+ verify_noerr( MPCreateSemaphore( maxcount, initialcount, &m_semaphore ) );
+ m_isOk = ( m_semaphore != kInvalidID );
+
+ if ( !IsOk() )
+ {
+ wxFAIL_MSG( wxT("Error when creating semaphore") );
+ }
+}
+
+wxSemaphoreInternal::~wxSemaphoreInternal()
+{
+ if (m_semaphore != kInvalidID)
+ MPDeleteSemaphore( m_semaphore );
+
+ MPYield();
+}
+
+wxSemaError wxSemaphoreInternal::WaitTimeout( unsigned long milliseconds )
+{
+ OSStatus err = MPWaitOnSemaphore( m_semaphore, milliseconds );
+ if (err != noErr)
+ {
+ if (err == kMPTimeoutErr)
+ return wxSEMA_TIMEOUT;
+
+ return wxSEMA_MISC_ERROR;
+ }
+
+ return wxSEMA_NO_ERROR;
+}
+
+wxSemaError wxSemaphoreInternal::Post()
+{
+ OSStatus err = MPSignalSemaphore( m_semaphore );
+ MPYield();
+ if (err != noErr)
+ return wxSEMA_MISC_ERROR;
+
+ return wxSEMA_NO_ERROR;
+}
+
+// ----------------------------------------------------------------------------
+// wxCondition implementation
+// ----------------------------------------------------------------------------
+
+#if 0
+
+class wxConditionInternal
+{
+public:
+ wxConditionInternal( wxMutex& mutex )
+ :
+ m_mutex( mutex ),
+ m_semaphore( 0, 1 ),
+ m_gate( 1, 1 )
+ {
+ m_waiters = 0;
+ m_signals = 0;
+ m_canceled = 0;
+ }
+
+ virtual ~wxConditionInternal() {}
+
+ bool IsOk() const
+ { return m_mutex.IsOk(); }
+
+ wxCondError Wait()
+ { return WaitTimeout( kDurationForever ); }
+
+ wxCondError WaitTimeout( unsigned long msectimeout );
+
+ wxCondError Signal()
+ { return DoSignal( false); }
+
+ wxCondError Broadcast()
+ { return DoSignal( true ); }
+
+private:
+ wxCondError DoSignal( bool signalAll );
+
+ wxMutex& m_mutex;
+ wxSemaphoreInternal m_semaphore; // Signals the waiting threads.
+ wxSemaphoreInternal m_gate;
+ wxCriticalSection m_varSection;
+ size_t m_waiters; // Number of threads waiting for a signal.
+ size_t m_signals; // Number of signals to send.
+ size_t m_canceled; // Number of canceled waiters in m_waiters.
+};
+
+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( wx("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 != noErr)
+ return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR;
+
+ return wxCOND_NO_ERROR;