📄 thread.cpp
字号:
return TRUE;
}
bool wxThreadInternal::Resume()
{
ThreadID current ;
OSErr err ;
err = MacGetCurrentThread( ¤t ) ;
wxASSERT( err == noErr ) ;
wxASSERT( current != m_tid ) ;
err = ::ThreadBeginCritical();
wxASSERT( err == noErr ) ;
if ( m_state != STATE_PAUSED && m_state != STATE_NEW )
{
err = ::ThreadEndCritical() ;
wxASSERT( err == noErr ) ;
wxLogSysError(_("Can not resume thread %x"), m_tid);
return FALSE;
}
err = ::SetThreadStateEndCritical(m_tid, kReadyThreadState, kNoThreadID);
m_state = STATE_RUNNING;
err = ::ThreadEndCritical() ;
wxASSERT( err == noErr ) ;
::YieldToAnyThread() ;
return TRUE;
}
// static functions
// ----------------
wxThread *wxThread::This()
{
wxMacStCritical critical ;
ThreadID current ;
OSErr err ;
err = MacGetCurrentThread( ¤t ) ;
for ( size_t i = 0 ; i < s_threads.Count() ; ++i )
{
if ( ( (wxThread*) s_threads[i] )->GetId() == current )
return (wxThread*) s_threads[i] ;
}
wxLogSysError(_("Couldn't get the current thread pointer"));
return NULL;
}
bool wxThread::IsMain()
{
ThreadID current ;
OSErr err ;
err = MacGetCurrentThread( ¤t ) ;
return current == gs_idMainThread;
}
#ifdef Yield
#undef Yield
#endif
void wxThread::Yield()
{
::YieldToAnyThread() ;
}
void wxThread::Sleep(unsigned long milliseconds)
{
UnsignedWide start, now;
Microseconds(&start);
double mssleep = milliseconds * 1000 ;
double msstart, msnow ;
msstart = (start.hi * 4294967296.0 + start.lo) ;
do
{
YieldToAnyThread();
Microseconds(&now);
msnow = (now.hi * 4294967296.0 + now.lo) ;
} while( msnow - msstart < mssleep );
}
int wxThread::GetCPUCount()
{
// we will use whatever MP API will be used for the new MP Macs
return 1;
}
unsigned long wxThread::GetCurrentId()
{
ThreadID current ;
MacGetCurrentThread( ¤t ) ;
return (unsigned long)current;
}
bool wxThread::SetConcurrency(size_t level)
{
wxASSERT_MSG( IsMain(), _T("should only be called from the main thread") );
// ok only for the default one
if ( level == 0 )
return 0;
// how many CPUs have we got?
if ( GetCPUCount() == 1 )
{
// don't bother with all this complicated stuff - on a single
// processor system it doesn't make much sense anyhow
return level == 1;
}
return TRUE ;
}
// ctor and dtor
// -------------
wxThread::wxThread(wxThreadKind kind)
{
g_numberOfThreads++;
m_internal = new wxThreadInternal();
m_isDetached = kind == wxTHREAD_DETACHED;
s_threads.Add( (void*) this ) ;
}
wxThread::~wxThread()
{
if (g_numberOfThreads>0)
{
g_numberOfThreads--;
}
#ifdef __WXDEBUG__
else
{
wxFAIL_MSG(wxT("More threads deleted than created."));
}
#endif
s_threads.Remove( (void*) this ) ;
if (m_internal != NULL) {
delete m_internal;
m_internal = NULL;
}
}
// create/start thread
// -------------------
wxThreadError wxThread::Create(unsigned int stackSize)
{
wxCriticalSectionLocker lock(m_critsect);
if ( !m_internal->Create(this, stackSize) )
return wxTHREAD_NO_RESOURCE;
return wxTHREAD_NO_ERROR;
}
wxThreadError wxThread::Run()
{
wxCriticalSectionLocker lock(m_critsect);
if ( m_internal->GetState() != STATE_NEW )
{
// actually, it may be almost any state at all, not only STATE_RUNNING
return wxTHREAD_RUNNING;
}
// the thread has just been created and is still suspended - let it run
return Resume();
}
// suspend/resume thread
// ---------------------
wxThreadError wxThread::Pause()
{
wxCriticalSectionLocker lock(m_critsect);
return m_internal->Suspend() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
}
wxThreadError wxThread::Resume()
{
wxCriticalSectionLocker lock(m_critsect);
return m_internal->Resume() ? wxTHREAD_NO_ERROR : wxTHREAD_MISC_ERROR;
}
// stopping thread
// ---------------
wxThread::ExitCode wxThread::Wait()
{
// although under MacOS we can wait for any thread, it's an error to
// wait for a detached one in wxWin API
wxCHECK_MSG( !IsDetached(), (ExitCode)-1,
_T("can't wait for detached thread") );
ExitCode rc = (ExitCode)-1;
(void)Delete(&rc);
m_internal->Free();
return rc;
}
wxThreadError wxThread::Delete(ExitCode *pRc)
{
ExitCode rc = 0;
// Delete() is always safe to call, so consider all possible states
// has the thread started to run?
bool shouldResume = FALSE;
{
wxCriticalSectionLocker lock(m_critsect);
if ( m_internal->GetState() == STATE_NEW )
{
// WinThreadStart() will see it and terminate immediately
m_internal->SetState(STATE_EXITED);
shouldResume = TRUE;
}
}
// is the thread paused?
if ( shouldResume || IsPaused() )
Resume();
// does is still run?
if ( IsRunning() )
{
if ( IsMain() )
{
// set flag for wxIsWaitingForThread()
gs_waitingForThread = TRUE;
#if wxUSE_GUI
wxBeginBusyCursor();
#endif // wxUSE_GUI
}
// ask the thread to terminate
{
wxCriticalSectionLocker lock(m_critsect);
m_internal->Cancel();
}
#if wxUSE_GUI
// simply wait for the thread to terminate
while( TestDestroy() )
{
::YieldToAnyThread() ;
}
#else // !wxUSE_GUI
// simply wait for the thread to terminate
while( TestDestroy() )
{
::YieldToAnyThread() ;
}
#endif // wxUSE_GUI/!wxUSE_GUI
if ( IsMain() )
{
gs_waitingForThread = FALSE;
#if wxUSE_GUI
wxEndBusyCursor();
#endif // wxUSE_GUI
}
}
if ( IsDetached() )
{
// if the thread exits normally, this is done in WinThreadStart, but in
// this case it would have been too early because
// MsgWaitForMultipleObject() would fail if the therad handle was
// closed while we were waiting on it, so we must do it here
delete this;
}
if ( pRc )
*pRc = rc;
return rc == (ExitCode)-1 ? wxTHREAD_MISC_ERROR : wxTHREAD_NO_ERROR;
}
wxThreadError wxThread::Kill()
{
if ( !IsRunning() )
return wxTHREAD_NOT_RUNNING;
// if ( !::TerminateThread(m_internal->GetHandle(), (DWORD)-1) )
{
wxLogSysError(_("Couldn't terminate thread"));
return wxTHREAD_MISC_ERROR;
}
m_internal->Free();
if ( IsDetached() )
{
delete this;
}
return wxTHREAD_NO_ERROR;
}
void wxThread::Exit(ExitCode status)
{
m_internal->Free();
if ( IsDetached() )
{
delete this;
}
m_internal->SetResult( status ) ;
/*
#if defined(__VISUALC__) || (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500))
_endthreadex((unsigned)status);
#else // !VC++
::ExitThread((DWORD)status);
#endif // VC++/!VC++
*/
wxFAIL_MSG(wxT("Couldn't return from ExitThread()!"));
}
// priority setting
// ----------------
// since all these calls are execute cooperatively we don't have to use the critical section
void wxThread::SetPriority(unsigned int prio)
{
m_internal->SetPriority(prio);
}
unsigned int wxThread::GetPriority() const
{
return m_internal->GetPriority();
}
unsigned long wxThread::GetId() const
{
return (unsigned long)m_internal->GetId();
}
bool wxThread::IsRunning() const
{
return m_internal->GetState() == STATE_RUNNING;
}
bool wxThread::IsAlive() const
{
return (m_internal->GetState() == STATE_RUNNING) ||
(m_internal->GetState() == STATE_PAUSED);
}
bool wxThread::IsPaused() const
{
return m_internal->GetState() == STATE_PAUSED;
}
bool wxThread::TestDestroy()
{
return m_internal->GetState() == STATE_CANCELED;
}
// ----------------------------------------------------------------------------
// 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()
{
long response;
bool hasThreadManager ;
hasThreadManager = Gestalt( gestaltThreadMgrAttr, &response) == noErr && response & 1;
#if !TARGET_CARBON
#if GENERATINGCFM
// verify presence of shared library
hasThreadManager = hasThreadManager && ((Ptr)NewThread != (Ptr)kUnresolvedCFragSymbolAddress);
#endif
#endif
if ( !hasThreadManager )
{
wxLogSysError( wxT("Thread Support is not available on this System") );
return FALSE ;
}
// no error return for GetCurrentThreadId()
MacGetCurrentThread( &gs_idMainThread ) ;
return TRUE;
}
void wxThreadModule::OnExit()
{
}
// ----------------------------------------------------------------------------
// under MacOS we don't have currently preemptive threads, so any thread may access
// the GUI at any time
// ----------------------------------------------------------------------------
void WXDLLEXPORT wxMutexGuiEnter()
{
}
void WXDLLEXPORT wxMutexGuiLeave()
{
}
void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
{
}
bool WXDLLEXPORT wxGuiOwnedByMainThread()
{
return false ;
}
// wake up the main thread
void WXDLLEXPORT wxWakeUpMainThread()
{
wxMacWakeUp() ;
}
bool WXDLLEXPORT wxIsWaitingForThread()
{
return false ;
}
#include "wx/thrimpl.cpp"
#endif // wxUSE_THREADS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -