⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 thread.cpp

📁 很牛的GUI源码wxWidgets-2.8.0.zip 可在多种平台下运行.
💻 CPP
📖 第 1 页 / 共 3 页
字号:
            m_shouldBeJoined = false;        }    }}void wxThreadInternal::Pause(){    // the state is set from the thread which pauses us first, this function    // is called later so the state should have been already set    wxCHECK_RET( m_state == STATE_PAUSED,                 wxT("thread must first be paused with wxThread::Pause().") );    // wait until the semaphore is Post()ed from Resume()    m_semSuspend.Wait();}void wxThreadInternal::Resume(){    wxCHECK_RET( m_state == STATE_PAUSED,                 wxT("can't resume thread which is not suspended.") );    // the thread might be not actually paused yet - if there were no call to    // TestDestroy() since the last call to Pause() for example    if ( IsReallyPaused() )    {        // wake up Pause()        m_semSuspend.Post();        // reset the flag        SetReallyPaused( false );    }    SetState( STATE_RUNNING );}// static functions// ----------------wxThread *wxThread::This(){    wxThread* thr = (wxThread*) MPGetTaskStorageValue( gs_tlsForWXThread ) ;    return thr;}bool wxThread::IsMain(){    return GetCurrentId() == gs_idMainThread || gs_idMainThread == kInvalidID ;}#ifdef Yield#undef Yield#endifvoid wxThread::Yield(){#if TARGET_API_MAC_OSX    CFRunLoopRunInMode( kCFRunLoopDefaultMode , 0 , true ) ;#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(            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 );}// also test whether we were pausedbool 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{public:    virtual bool OnInit();    virtual void OnExit();private:    DECLARE_DYNAMIC_CLASS(wxThreadModule)};IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule)bool wxThreadModule::OnInit(){    bool hasThreadManager = #ifdef __LP64__         true ; // TODO VERIFY IN NEXT BUILD#else        MPLibraryIsLoaded();#endif    if ( !hasThreadManager )    {        wxLogError( wxT("MP thread support is not available on this system" ) ) ;        return false;    }    // main thread's This() is NULL    verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread ) ) ;    verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread, 0 ) ) ;    gs_idMainThread = wxThread::GetCurrentId();    gs_critsectWaitingForGui = new wxCriticalSection();    gs_critsectGui = new wxCriticalSection();    gs_critsectGui->Enter();    return true;}void wxThreadModule::OnExit(){    if ( gs_critsectGui )    {        if ( !wxGuiOwnedByMainThread() )        {            gs_critsectGui->Enter();            gs_bGuiOwnedByMainThread = true;        }        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()!") );    if ( !gs_critsectWaitingForGui )        return;    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 + -