+ wxASSERT_MSG( g_numberOfThreads>0 , wxT("More threads deleted than created.") ) ;
+
+ g_numberOfThreads--;
+
+#ifdef __WXDEBUG__
+ m_critsect.Enter();
+
+ // check that the thread either exited or couldn't be created
+ if ( m_internal->GetState() != STATE_EXITED &&
+ m_internal->GetState() != STATE_NEW )
+ {
+ wxLogDebug(
+ wxT("The thread %ld is being destroyed although it is still running! The application may crash."),
+ GetId() );
+ }
+
+ m_critsect.Leave();
+#endif
+
+ wxDELETE( m_internal ) ;
+}
+
+wxThreadError wxThread::Create( unsigned int stackSize )
+{
+ wxCriticalSectionLocker lock(m_critsect);
+
+ if ( m_isDetached )
+ m_internal->Detach() ;
+
+ if ( !m_internal->Create(this, stackSize) )
+ {
+ m_internal->SetState( STATE_EXITED );
+
+ return wxTHREAD_NO_RESOURCE;
+ }
+
+ return wxTHREAD_NO_ERROR;
+}
+
+wxThreadError wxThread::Run()
+{
+ wxCriticalSectionLocker lock(m_critsect);
+
+ wxCHECK_MSG( m_internal->GetId(), wxTHREAD_MISC_ERROR,
+ wxT("must call wxThread::Create() first") );
+
+ return m_internal->Run();
+}
+
+// -----------------------------------------------------------------------------
+// pause/resume
+// -----------------------------------------------------------------------------
+
+wxThreadError wxThread::Pause()
+{
+ wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
+ _T("a thread can't pause itself") );
+
+ wxCriticalSectionLocker lock(m_critsect);
+
+ if ( m_internal->GetState() != STATE_RUNNING )
+ {
+ wxLogDebug( wxT("Can't pause thread which is not running.") );
+
+ return wxTHREAD_NOT_RUNNING;
+ }
+
+ // just set a flag, the thread will be really paused only during the next
+ // call to TestDestroy()
+ m_internal->SetState( STATE_PAUSED );
+
+ return wxTHREAD_NO_ERROR;
+}
+
+wxThreadError wxThread::Resume()
+{
+ wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
+ wxT("a thread can't resume itself") );
+
+ wxCriticalSectionLocker lock(m_critsect);
+
+ wxThreadState state = m_internal->GetState();
+
+ switch ( state )
+ {
+ case STATE_PAUSED:
+ m_internal->Resume();
+ return wxTHREAD_NO_ERROR;
+
+ case STATE_EXITED:
+ return wxTHREAD_NO_ERROR;
+
+ default:
+ wxLogDebug( wxT("Attempt to resume a thread which is not paused.") );
+
+ return wxTHREAD_MISC_ERROR;
+ }
+}
+
+// -----------------------------------------------------------------------------
+// exiting thread
+// -----------------------------------------------------------------------------
+
+wxThread::ExitCode wxThread::Wait()
+{
+ wxCHECK_MSG( This() != this, (ExitCode)-1,
+ wxT("a thread can't wait for itself") );
+
+ wxCHECK_MSG( !m_isDetached, (ExitCode)-1,
+ wxT("can't wait for detached thread") );
+
+ m_internal->Wait();
+
+ return m_internal->GetExitCode();
+}
+
+wxThreadError wxThread::Delete(ExitCode *rc)
+{
+ wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
+ wxT("a thread can't delete itself") );
+
+ bool isDetached = m_isDetached;
+
+ m_critsect.Enter();
+ wxThreadState state = m_internal->GetState();
+
+ // ask the thread to stop
+ m_internal->SetCancelFlag();
+
+ m_critsect.Leave();
+
+ switch ( state )
+ {
+ case STATE_NEW:
+ // we need to wake up the thread so that PthreadStart() will
+ // terminate - right now it's blocking on run semaphore in
+ // PthreadStart()
+ m_internal->SignalRun();
+
+ // fall through
+
+ case STATE_EXITED:
+ // nothing to do
+ break;
+
+ case STATE_PAUSED:
+ // resume the thread first
+ m_internal->Resume();
+
+ // fall through
+
+ default:
+ if ( !isDetached )
+ {
+ // wait until the thread stops
+ m_internal->Wait();
+
+ if ( rc )
+ {
+ // return the exit code of the thread
+ *rc = m_internal->GetExitCode();
+ }
+ }
+ }
+
+ return wxTHREAD_NO_ERROR;
+}
+
+wxThreadError wxThread::Kill()
+{
+ wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR,
+ wxT("a thread can't kill itself") );
+
+ switch ( m_internal->GetState() )
+ {
+ case STATE_NEW:
+ case STATE_EXITED:
+ return wxTHREAD_NOT_RUNNING;
+
+ case STATE_PAUSED:
+ // resume the thread first
+ Resume();
+
+ // fall through
+
+ default:
+ OSStatus err = MPTerminateTask( m_internal->GetId() , -1 ) ;
+ if (err != noErr)
+ {
+ wxLogError( wxT("Failed to terminate a thread.") );
+
+ return wxTHREAD_MISC_ERROR;
+ }
+
+ if ( m_isDetached )
+ {
+ delete this ;
+ }
+ else
+ {
+ // this should be retrieved by Wait actually
+ m_internal->SetExitCode( (void*)-1 );
+ }
+
+ return wxTHREAD_NO_ERROR;
+ }
+}
+
+void wxThread::Exit( ExitCode status )
+{
+ wxASSERT_MSG( This() == this,
+ wxT("wxThread::Exit() can only be called in the context of the same thread") );
+
+ // don't enter m_critsect before calling OnExit() because the user code
+ // might deadlock if, for example, it signals a condition in OnExit() (a
+ // common case) while the main thread calls any of functions entering
+ // m_critsect on us (almost all of them do)
+ OnExit();
+
+ MPTaskID threadid = m_internal->GetId();
+
+ if ( IsDetached() )
+ {
+ delete this;
+ }
+ else // joinable
+ {
+ // update the status of the joinable thread
+ wxCriticalSectionLocker lock( m_critsect );
+ m_internal->SetState( STATE_EXITED );
+ }
+
+ MPTerminateTask( threadid, (long)status );