X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/1f0c8f31f407ecfce909060464c0ea655221cdab..71a09c3579dd5cb4cd8fa7fdc143561cbff74e12:/src/osx/carbon/thread.cpp?ds=inline diff --git a/src/osx/carbon/thread.cpp b/src/osx/carbon/thread.cpp index 6d23905e80..f4f3d5bd3d 100644 --- a/src/osx/carbon/thread.cpp +++ b/src/osx/carbon/thread.cpp @@ -1,10 +1,9 @@ ///////////////////////////////////////////////////////////////////////////// -// Name: src/mac/carbon/thread.cpp +// Name: src/osx/carbon/thread.cpp // Purpose: wxThread Implementation // Author: Original from Wolfram Gloger/Guilhem Lavaux/Vadim Zeitlin // Modified by: Aj Lavin, Stefan Csomor // Created: 04/22/98 -// RCS-ID: $Id$ // Copyright: (c) Wolfram Gloger (1996, 1997); Guilhem Lavaux (1998), // Vadim Zeitlin (1999), Stefan Csomor (2000) // Licence: wxWindows licence @@ -25,7 +24,12 @@ #include "wx/thread.h" +#if wxOSX_USE_COCOA_OR_CARBON #include +#else +#include +#endif + #include "wx/osx/uma.h" // the possible states of the thread: @@ -44,7 +48,7 @@ enum wxThreadState // ---------------------------------------------------------------------------- // the task ID of the main thread -static wxThreadIdType gs_idMainThread = kInvalidID; +wxThreadIdType wxThread::ms_idMainThread = kInvalidID; // this is the Per-Task Storage for the pointer to the appropriate wxThread TaskStorageIndex gs_tlsForWXThread = 0; @@ -101,7 +105,7 @@ MPCriticalRegionID gs_guiCritical = kInvalidID; // wxCriticalSection // ---------------------------------------------------------------------------- -wxCriticalSection::wxCriticalSection() +wxCriticalSection::wxCriticalSection( wxCriticalSectionType WXUNUSED(critSecType) ) { MPCreateCriticalRegion( (MPCriticalRegionID*) &m_critRegion ); } @@ -116,6 +120,11 @@ void wxCriticalSection::Enter() MPEnterCriticalRegion( (MPCriticalRegionID) m_critRegion, kDurationForever ); } +bool wxCriticalSection::TryEnter() +{ + return MPEnterCriticalRegion( (MPCriticalRegionID) m_critRegion, kDurationImmediate ) == noErr; +} + void wxCriticalSection::Leave() { MPExitCriticalRegion( (MPCriticalRegionID) m_critRegion ); @@ -129,270 +138,6 @@ void wxCriticalSection::Leave() #define wxUSE_MAC_CRITICAL_REGION_MUTEX 1 #define wxUSE_MAC_PTHREADS_MUTEX 0 -#if wxUSE_MAC_PTHREADS_MUTEX - -#include - - -class wxMutexInternal -{ -public: - wxMutexInternal( wxMutexType mutexType ); - ~wxMutexInternal(); - - wxMutexError Lock(); - wxMutexError TryLock(); - wxMutexError Unlock(); - - bool IsOk() const - { return m_isOk; } - -private: - pthread_mutex_t m_mutex; - bool m_isOk; - - // wxConditionInternal uses our m_mutex - friend class wxConditionInternal; -}; - -#ifdef HAVE_PTHREAD_MUTEXATTR_T -// on some systems pthread_mutexattr_settype() is not in the headers (but it is -// in the library, otherwise we wouldn't compile this code at all) -extern "C" int pthread_mutexattr_settype( pthread_mutexattr_t *, int ); -#endif - -wxMutexInternal::wxMutexInternal( wxMutexType mutexType ) -{ - int err; - switch ( mutexType ) - { - case wxMUTEX_RECURSIVE: - // support recursive locks like Win32, i.e. a thread can lock a - // mutex which it had itself already locked - // - // unfortunately initialization of recursive mutexes is non - // portable, so try several methods -#ifdef HAVE_PTHREAD_MUTEXATTR_T - { - pthread_mutexattr_t attr; - pthread_mutexattr_init( &attr ); - pthread_mutexattr_settype( &attr, PTHREAD_MUTEX_RECURSIVE ); - - err = pthread_mutex_init( &m_mutex, &attr ); - } -#elif defined(HAVE_PTHREAD_RECURSIVE_MUTEX_INITIALIZER) - // we can use this only as initializer so we have to assign it - // first to a temp var - assigning directly to m_mutex wouldn't - // even compile - { - pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; - m_mutex = mutex; - } -#else // no recursive mutexes - err = EINVAL; -#endif // HAVE_PTHREAD_MUTEXATTR_T/... - break; - - default: - wxFAIL_MSG( wxT("unknown mutex type") ); - // fall through - - case wxMUTEX_DEFAULT: - err = pthread_mutex_init( &m_mutex, NULL ); - break; - } - - m_isOk = err == 0; - if ( !m_isOk ) - { - wxLogApiError( wxT("pthread_mutex_init()"), err ); - } -} - -wxMutexInternal::~wxMutexInternal() -{ - if ( m_isOk ) - { - int err = pthread_mutex_destroy( &m_mutex ); - if ( err != 0 ) - { - wxLogApiError( wxT("pthread_mutex_destroy()"), err ); - } - } -} - -wxMutexError wxMutexInternal::Lock() -{ - int err = pthread_mutex_lock( &m_mutex ); - switch ( err ) - { - case EDEADLK: - // only error checking mutexes return this value and so it's an - // unexpected situation -- hence use assert, not wxLogDebug - wxFAIL_MSG( wxT("mutex deadlock prevented") ); - return wxMUTEX_DEAD_LOCK; - - case EINVAL: - wxLogDebug( wxT("pthread_mutex_lock(): mutex not initialized.") ); - break; - - case 0: - return wxMUTEX_NO_ERROR; - - default: - wxLogApiError( wxT("pthread_mutex_lock()"), err ); - } - - return wxMUTEX_MISC_ERROR; -} - -wxMutexError wxMutexInternal::TryLock() -{ - int err = pthread_mutex_trylock( &m_mutex ); - switch ( err ) - { - case EBUSY: - // not an error: mutex is already locked, but we're prepared for this case - return wxMUTEX_BUSY; - - case EINVAL: - wxLogDebug( wxT("pthread_mutex_trylock(): mutex not initialized.") ); - break; - - case 0: - return wxMUTEX_NO_ERROR; - - default: - wxLogApiError( wxT("pthread_mutex_trylock()"), err ); - } - - return wxMUTEX_MISC_ERROR; -} - -wxMutexError wxMutexInternal::Unlock() -{ - int err = pthread_mutex_unlock( &m_mutex ); - switch ( err ) - { - case EPERM: - // we don't own the mutex - return wxMUTEX_UNLOCKED; - - case EINVAL: - wxLogDebug( wxT("pthread_mutex_unlock(): mutex not initialized.") ); - break; - - case 0: - return wxMUTEX_NO_ERROR; - - default: - wxLogApiError( wxT("pthread_mutex_unlock()"), err ); - } - - return wxMUTEX_MISC_ERROR; -} - -#endif - -#if wxUSE_MAC_SEMAPHORE_MUTEX - -class wxMutexInternal -{ -public: - wxMutexInternal( wxMutexType mutexType ); - virtual ~wxMutexInternal(); - - bool IsOk() const - { return m_isOk; } - - wxMutexError Lock(); - wxMutexError TryLock(); - wxMutexError Unlock(); - -private: - MPSemaphoreID m_semaphore; - bool m_isOk; -}; - -wxMutexInternal::wxMutexInternal(wxMutexType mutexType ) -{ - m_isOk = false; - m_semaphore = kInvalidID; - OSStatus err = noErr; - - switch ( mutexType ) - { - case wxMUTEX_DEFAULT : - verify_noerr( MPCreateBinarySemaphore( &m_semaphore ) ); - m_isOk = ( m_semaphore != kInvalidID ); - break; - - case wxMUTEX_RECURSIVE : - wxFAIL_MSG( wxT("Recursive Mutex not supported yet") ); - break; - - default : - wxFAIL_MSG( wxT("Unknown mutex type") ); - break; - } -} - -wxMutexInternal::~wxMutexInternal() -{ - if ( m_semaphore != kInvalidID ) - MPDeleteSemaphore( m_semaphore ); - - MPYield(); -} - -wxMutexError wxMutexInternal::Lock() -{ - wxCHECK_MSG( m_isOk, wxMUTEX_MISC_ERROR, wxT("Invalid Mutex") ); - OSStatus err = MPWaitOnSemaphore( m_semaphore, kDurationForever ); - if (err != noErr) - { - wxLogSysError( wxT("Could not lock mutex") ); - - return wxMUTEX_MISC_ERROR; - } - - return wxMUTEX_NO_ERROR; -} - -wxMutexError wxMutexInternal::TryLock() -{ - wxCHECK_MSG( m_isOk, wxMUTEX_MISC_ERROR, wxT("Invalid Mutex") ); - OSStatus err = MPWaitOnSemaphore( m_semaphore, kDurationImmediate ); - if (err != noErr) - { - if (err == kMPTimeoutErr) - return wxMUTEX_BUSY; - - wxLogSysError( wxT("Could not try lock mutex") ); - - return wxMUTEX_MISC_ERROR; - } - - return wxMUTEX_NO_ERROR; -} - -wxMutexError wxMutexInternal::Unlock() -{ - wxCHECK_MSG( m_isOk, wxMUTEX_MISC_ERROR, wxT("Invalid Mutex") ); - OSStatus err = MPSignalSemaphore( m_semaphore ); - - MPYield(); - if (err != noErr) - { - wxLogSysError( wxT("Could not unlock mutex") ); - return wxMUTEX_MISC_ERROR; - } - - return wxMUTEX_NO_ERROR; -} - -#endif - #if wxUSE_MAC_CRITICAL_REGION_MUTEX class wxMutexInternal @@ -578,177 +323,6 @@ wxSemaError wxSemaphoreInternal::Post() // wxCondition implementation // ---------------------------------------------------------------------------- -#if 0 - -class wxConditionInternal -{ -public: - wxConditionInternal( wxMutex& mutex ) - : - m_mutex( mutex ), - m_semaphore( 0, 1 ), - m_gate( 1, 1 ) - { - m_waiters = 0; - m_signals = 0; - m_canceled = 0; - } - - virtual ~wxConditionInternal() {} - - bool IsOk() const - { return m_mutex.IsOk(); } - - wxCondError Wait() - { return WaitTimeout( kDurationForever ); } - - wxCondError WaitTimeout( unsigned long msectimeout ); - - wxCondError Signal() - { return DoSignal( false); } - - wxCondError Broadcast() - { return DoSignal( true ); } - -private: - wxCondError DoSignal( bool signalAll ); - - wxMutex& m_mutex; - wxSemaphoreInternal m_semaphore; // Signals the waiting threads. - wxSemaphoreInternal m_gate; - wxCriticalSection m_varSection; - size_t m_waiters; // Number of threads waiting for a signal. - size_t m_signals; // Number of signals to send. - size_t m_canceled; // Number of canceled waiters in m_waiters. -}; - -wxCondError wxConditionInternal::WaitTimeout( unsigned long msectimeout ) -{ - m_gate.Wait(); - - if ( ++ m_waiters == INT_MAX ) - { - m_varSection.Enter(); - - m_waiters -= m_canceled; - m_signals -= m_canceled; - m_canceled = 0; - - m_varSection.Leave(); - } - - m_gate.Post(); - m_mutex.Unlock(); - - wxSemaError err = m_semaphore.WaitTimeout( msectimeout); - wxASSERT( err == wxSEMA_NO_ERROR || err == wxSEMA_TIMEOUT); - - m_varSection.Enter(); - - if ( err != wxSEMA_NO_ERROR ) - { - if ( m_signals > m_canceled ) - { - // A signal is being sent after we timed out. - if ( m_waiters == m_signals ) - { - // There are no excess waiters to catch the signal, so - // we must throw it away. - wxSemaError err2 = m_semaphore.Wait(); - if ( err2 != wxSEMA_NO_ERROR ) - { - wxLogSysError( wx("Error while waiting on semaphore") ); - } - - wxASSERT( err2 == wxSEMA_NO_ERROR); - - --m_waiters; - if ( --m_signals == m_canceled ) - { - // This was the last signal. open the gate. - wxASSERT( m_waiters == m_canceled ); - m_gate.Post(); - } - } - else - { - // There are excess waiters to catch the signal, leave it be. - --m_waiters; - } - } - else - { - // No signals is being sent: - // the gate may be open or closed, so we can't touch m_waiters. - ++m_canceled; - ++m_signals; - } - } - else - { - // We caught a signal. - wxASSERT( m_signals > m_canceled ); - - --m_waiters; - - if ( --m_signals == m_canceled) - { - // This was the last signal. open the gate. - wxASSERT( m_waiters == m_canceled ); - - m_gate.Post(); - } - } - - m_varSection.Leave(); - m_mutex.Lock(); - - if (err != noErr) - return err == wxSEMA_TIMEOUT ? wxCOND_TIMEOUT : wxCOND_MISC_ERROR; - - return wxCOND_NO_ERROR; -} - - -wxCondError wxConditionInternal::DoSignal( bool signalAll) -{ - m_gate.Wait(); - m_varSection.Enter(); - - wxASSERT( m_signals == m_canceled ); - - if ( m_waiters == m_canceled) - { - m_varSection.Leave(); - m_gate.Post(); - return wxCOND_NO_ERROR; - } - - if ( m_canceled > 0) - { - m_waiters -= m_canceled; - m_signals = 0; - m_canceled = 0; - } - - m_signals = signalAll ? m_waiters : 1; - size_t n = m_signals; - - m_varSection.Leave(); - - // Let the waiters inherit the gate lock. - - do - { - wxSemaError err = m_semaphore.Post(); - wxASSERT( err == wxSEMA_NO_ERROR ); - } - while ( --n ); - - return wxCOND_NO_ERROR; -} - -#else class wxConditionInternal { public: @@ -773,7 +347,7 @@ private: wxMutex& m_mutex; wxSemaphore m_semaphore; - DECLARE_NO_COPY_CLASS(wxConditionInternal) + wxDECLARE_NO_COPY_CLASS(wxConditionInternal); }; wxConditionInternal::wxConditionInternal( wxMutex& mutex ) @@ -879,7 +453,6 @@ wxCondError wxConditionInternal::Broadcast() return wxCOND_NO_ERROR; } -#endif // ---------------------------------------------------------------------------- // wxCriticalSection implementation @@ -901,7 +474,7 @@ public: { m_tid = kInvalidID; m_state = STATE_NEW; - m_prio = WXTHREAD_DEFAULT_PRIORITY; + m_prio = wxPRIORITY_DEFAULT; m_notifyQueueId = kInvalidID; m_exitcode = 0; m_cancelled = false ; @@ -1082,6 +655,9 @@ bool wxThreadInternal::Create( wxThread *thread, unsigned int stackSize ) wxASSERT_MSG( m_state == STATE_NEW && !m_tid, wxT("Create()ing thread twice?") ); + if ( thread->IsDetached() ) + Detach(); + OSStatus err = noErr; m_thread = thread; @@ -1090,7 +666,7 @@ bool wxThreadInternal::Create( wxThread *thread, unsigned int stackSize ) OSStatus err = MPCreateQueue( &m_notifyQueueId ); if (err != noErr) { - wxLogSysError( wxT("Cant create the thread event queue") ); + wxLogSysError( wxT("Can't create the thread event queue") ); return false; } @@ -1109,7 +685,7 @@ bool wxThreadInternal::Create( wxThread *thread, unsigned int stackSize ) return false; } - if ( m_prio != WXTHREAD_DEFAULT_PRIORITY ) + if ( m_prio != wxPRIORITY_DEFAULT ) SetPriority( m_prio ); return true; @@ -1227,11 +803,6 @@ wxThread *wxThread::This() return thr; } -bool wxThread::IsMain() -{ - return GetCurrentId() == gs_idMainThread || gs_idMainThread == kInvalidID ; -} - #ifdef Yield #undef Yield #endif @@ -1279,7 +850,6 @@ wxThread::~wxThread() g_numberOfThreads--; -#ifdef __WXDEBUG__ m_critsect.Enter(); // check that the thread either exited or couldn't be created @@ -1292,7 +862,6 @@ wxThread::~wxThread() } m_critsect.Leave(); -#endif wxDELETE( m_internal ) ; } @@ -1301,13 +870,9 @@ 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; } @@ -1318,6 +883,17 @@ wxThreadError wxThread::Run() { wxCriticalSectionLocker lock(m_critsect); + // Create the thread if it wasn't created yet with an explicit + // Create() call: + if ( m_internal->GetId() == kInvalidID ) + { + if ( !m_internal->Create(this, stackSize) ) + { + m_internal->SetState( STATE_EXITED ); + return wxTHREAD_NO_RESOURCE; + } + } + wxCHECK_MSG( m_internal->GetId(), wxTHREAD_MISC_ERROR, wxT("must call wxThread::Create() first") ); @@ -1331,7 +907,7 @@ wxThreadError wxThread::Run() wxThreadError wxThread::Pause() { wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR, - _T("a thread can't pause itself") ); + wxT("a thread can't pause itself") ); wxCriticalSectionLocker lock(m_critsect); @@ -1378,7 +954,7 @@ wxThreadError wxThread::Resume() // exiting thread // ----------------------------------------------------------------------------- -wxThread::ExitCode wxThread::Wait() +wxThread::ExitCode wxThread::Wait(wxThreadWait WXUNUSED(waitMode)) { wxCHECK_MSG( This() != this, (ExitCode)-1, wxT("a thread can't wait for itself") ); @@ -1391,7 +967,7 @@ wxThread::ExitCode wxThread::Wait() return m_internal->GetExitCode(); } -wxThreadError wxThread::Delete(ExitCode *rc) +wxThreadError wxThread::Delete(ExitCode *rc, wxThreadWait WXUNUSED(waitMode)) { wxCHECK_MSG( This() != this, wxTHREAD_MISC_ERROR, wxT("a thread can't delete itself") ); @@ -1543,8 +1119,7 @@ bool wxThread::TestDestroy() void wxThread::SetPriority(unsigned int prio) { - wxCHECK_RET( ((int)WXTHREAD_MIN_PRIORITY <= (int)prio) && - ((int)prio <= (int)WXTHREAD_MAX_PRIORITY), + wxCHECK_RET( wxPRIORITY_MIN <= prio && prio <= wxPRIORITY_MAX, wxT("invalid thread priority") ); wxCriticalSectionLocker lock(m_critsect); @@ -1566,14 +1141,14 @@ void wxThread::SetPriority(unsigned int prio) unsigned int wxThread::GetPriority() const { - wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast + wxCriticalSectionLocker lock(const_cast(m_critsect)); return m_internal->GetPriority(); } unsigned long wxThread::GetId() const { - wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast + wxCriticalSectionLocker lock(const_cast(m_critsect)); return (unsigned long)m_internal->GetId(); } @@ -1629,8 +1204,8 @@ IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule) bool wxThreadModule::OnInit() { - bool hasThreadManager = -#ifdef __LP64__ + bool hasThreadManager = +#ifdef __LP64__ true ; // TODO VERIFY IN NEXT BUILD #else MPLibraryIsLoaded(); @@ -1647,7 +1222,7 @@ bool wxThreadModule::OnInit() verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread ) ) ; verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread, 0 ) ) ; - gs_idMainThread = wxThread::GetCurrentId(); + wxThread::ms_idMainThread = wxThread::GetCurrentId(); gs_critsectWaitingForGui = new wxCriticalSection(); gs_critsectGui = new wxCriticalSection(); @@ -1667,12 +1242,10 @@ void wxThreadModule::OnExit() } gs_critsectGui->Leave(); - delete gs_critsectGui; - gs_critsectGui = NULL; + wxDELETE(gs_critsectGui); } - delete gs_critsectWaitingForGui; - gs_critsectWaitingForGui = NULL; + wxDELETE(gs_critsectWaitingForGui); } // ----------------------------------------------------------------------------