📄 mpthread.cpp
字号:
#endif MPYield();}void wxThread::Sleep(unsigned long milliseconds){ AbsoluteTime wakeup = AddDurationToAbsolute( milliseconds, UpTime()); MPDelayUntil( & wakeup);}int wxThread::GetCPUCount(){ return MPProcessors();}unsigned long wxThread::GetCurrentId(){ return (unsigned long)MPCurrentTaskID();}bool wxThread::SetConcurrency(size_t level){ // Cannot be set in MacOS. return false;}wxThread::wxThread(wxThreadKind kind){ g_numberOfThreads++; m_internal = new wxThreadInternal(); m_isDetached = (kind == wxTHREAD_DETACHED);}wxThread::~wxThread(){ 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(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId()); } m_critsect.Leave();#endif // __WXDEBUG__ 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) == false ) { 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, _T("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(_T("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, _T("a thread can't wait for itself") ); wxCHECK_MSG( !m_isDetached, (ExitCode)-1, _T("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, _T("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(); } } //else: can't wait for detached threads } return wxTHREAD_NO_ERROR;}wxThreadError wxThread::Kill(){ wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR, _T("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 ) { wxLogError(_("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, _T("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(); MPTerminateTask( m_internal->GetId() , (long) status) ; if ( IsDetached() ) { delete this; } else // joinable { // update the status of the joinable thread wxCriticalSectionLocker lock(m_critsect); m_internal->SetState(STATE_EXITED); }}// also test whether we were pausedbool wxThread::TestDestroy(){ wxASSERT_MSG( This() == this, _T("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 // try 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{public: virtual bool OnInit(); virtual void OnExit();private: DECLARE_DYNAMIC_CLASS(wxThreadModule)};IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)bool wxThreadModule::OnInit(){ if ( !wxMacMPThreadsInitVerify() ) { return false ; } verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread ) ) ; // main thread's This() is NULL verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , NULL ) ) ; gs_idMainThread = wxThread::GetCurrentId() ; gs_critsectWaitingForGui = new wxCriticalSection(); gs_critsectGui = new wxCriticalSection(); gs_critsectGui->Enter(); return true;}void wxThreadModule::OnExit(){ if ( gs_critsectGui ) { gs_critsectGui->Leave(); delete gs_critsectGui; gs_critsectGui = NULL; } delete gs_critsectWaitingForGui; gs_critsectWaitingForGui = NULL;}// ----------------------------------------------------------------------------// GUI Serialization copied from MSW implementation// ----------------------------------------------------------------------------void WXDLLIMPEXP_BASE wxMutexGuiEnter(){ // this would dead lock everything... wxASSERT_MSG( !wxThread::IsMain(), wxT("main thread doesn't want to block in wxMutexGuiEnter()!") ); // the order in which we enter the critical sections here is crucial!! // set the flag telling to the main thread that we want to do some GUI { wxCriticalSectionLocker enter(*gs_critsectWaitingForGui); gs_nWaitingForGui++; } wxWakeUpMainThread(); // now we may block here because the main thread will soon let us in // (during the next iteration of OnIdle()) gs_critsectGui->Enter();}void WXDLLIMPEXP_BASE wxMutexGuiLeave(){ wxCriticalSectionLocker enter(*gs_critsectWaitingForGui); if ( wxThread::IsMain() ) { gs_bGuiOwnedByMainThread = false; } else { // decrement the number of threads waiting for GUI access now wxASSERT_MSG( gs_nWaitingForGui > 0, wxT("calling wxMutexGuiLeave() without entering it first?") ); gs_nWaitingForGui--; wxWakeUpMainThread(); } gs_critsectGui->Leave();}void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter(){ wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); wxCriticalSectionLocker enter(*gs_critsectWaitingForGui); if ( gs_nWaitingForGui == 0 ) { // no threads are waiting for GUI - so we may acquire the lock without // any danger (but only if we don't already have it) if ( !wxGuiOwnedByMainThread() ) { gs_critsectGui->Enter(); gs_bGuiOwnedByMainThread = true; } //else: already have it, nothing to do } else { // some threads are waiting, release the GUI lock if we have it if ( wxGuiOwnedByMainThread() ) { wxMutexGuiLeave(); } //else: some other worker thread is doing GUI }}bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread(){ return gs_bGuiOwnedByMainThread;}// wake up the main threadvoid WXDLLEXPORT wxWakeUpMainThread(){ wxMacWakeUp() ;}// ----------------------------------------------------------------------------// include common implementation code// ----------------------------------------------------------------------------#include "wx/thrimpl.cpp"#endif // wxUSE_THREADS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -