+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 );
+}
+
+// also test whether we were paused
+bool wxThread::TestDestroy()
+{
+ wxASSERT_MSG( This() == this,
+ wxT("wxThread::TestDestroy() can only be called in the context of the same thread") );
+
+ m_critsect.Enter();
+
+ if ( m_internal->GetState() == STATE_PAUSED )
+ {
+ m_internal->SetReallyPaused( true );
+
+ // leave the crit section or the other threads will stop too if they attempt
+ // to call any of (seemingly harmless) IsXXX() functions while we sleep
+ m_critsect.Leave();
+
+ m_internal->Pause();
+ }
+ else
+ {
+ // thread wasn't requested to pause, nothing to do
+ m_critsect.Leave();
+ }
+
+ return m_internal->WasCancelled();
+}
+
+// -----------------------------------------------------------------------------
+// priority setting
+// -----------------------------------------------------------------------------
+
+void wxThread::SetPriority(unsigned int prio)
+{
+ wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY <= (int)prio) &&
+ ((int)prio <= (int)WXTHREAD_MAX_PRIORITY),
+ wxT("invalid thread priority") );
+
+ wxCriticalSectionLocker lock(m_critsect);
+
+ switch ( m_internal->GetState() )
+ {
+ case STATE_RUNNING:
+ case STATE_PAUSED:
+ case STATE_NEW:
+ // thread not yet started, priority will be set when it is
+ m_internal->SetPriority( prio );
+ break;
+
+ case STATE_EXITED:
+ default:
+ wxFAIL_MSG( wxT("impossible to set thread priority in this state") );
+ }
+}
+
+unsigned int wxThread::GetPriority() const
+{
+ wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
+
+ return m_internal->GetPriority();
+}
+
+unsigned long wxThread::GetId() const
+{
+ wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
+
+ return (unsigned long)m_internal->GetId();
+}
+
+// -----------------------------------------------------------------------------
+// state tests
+// -----------------------------------------------------------------------------
+
+bool wxThread::IsRunning() const
+{
+ wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect);
+
+ return m_internal->GetState() == STATE_RUNNING;
+}
+
+bool wxThread::IsAlive() const
+{
+ wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
+
+ switch ( m_internal->GetState() )
+ {
+ case STATE_RUNNING:
+ case STATE_PAUSED:
+ return true;
+
+ default:
+ return false;
+ }
+}
+
+bool wxThread::IsPaused() const
+{
+ wxCriticalSectionLocker lock((wxCriticalSection&)m_critsect);
+
+ return (m_internal->GetState() == STATE_PAUSED);
+}
+
+// ----------------------------------------------------------------------------
+// Automatic initialization for thread module
+// ----------------------------------------------------------------------------
+
+class wxThreadModule : public wxModule
+{