/////////////////////////////////////////////////////////////////////////////
-// 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
// ----------------------------------------------------------------------------
// 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;
// wxCriticalSection
// ----------------------------------------------------------------------------
-wxCriticalSection::wxCriticalSection()
+wxCriticalSection::wxCriticalSection( wxCriticalSectionType WXUNUSED(critSecType) )
{
MPCreateCriticalRegion( (MPCriticalRegionID*) &m_critRegion );
}
MPEnterCriticalRegion( (MPCriticalRegionID) m_critRegion, kDurationForever );
}
+bool wxCriticalSection::TryEnter()
+{
+ return MPEnterCriticalRegion( (MPCriticalRegionID) m_critRegion, kDurationImmediate ) == noErr;
+}
+
void wxCriticalSection::Leave()
{
MPExitCriticalRegion( (MPCriticalRegionID) m_critRegion );
#define wxUSE_MAC_CRITICAL_REGION_MUTEX 1
#define wxUSE_MAC_PTHREADS_MUTEX 0
-#if wxUSE_MAC_PTHREADS_MUTEX
-
-#include <pthread.h>
-
-
-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
// 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:
wxMutex& m_mutex;
wxSemaphore m_semaphore;
- DECLARE_NO_COPY_CLASS(wxConditionInternal)
+ wxDECLARE_NO_COPY_CLASS(wxConditionInternal);
};
wxConditionInternal::wxConditionInternal( wxMutex& mutex )
return wxCOND_NO_ERROR;
}
-#endif
// ----------------------------------------------------------------------------
// wxCriticalSection implementation
{
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 ;
wxASSERT_MSG( m_state == STATE_NEW && !m_tid,
wxT("Create()ing thread twice?") );
+ if ( thread->IsDetached() )
+ Detach();
+
OSStatus err = noErr;
m_thread = thread;
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;
}
return false;
}
- if ( m_prio != WXTHREAD_DEFAULT_PRIORITY )
+ if ( m_prio != wxPRIORITY_DEFAULT )
SetPriority( m_prio );
return true;
return thr;
}
-bool wxThread::IsMain()
-{
- return GetCurrentId() == gs_idMainThread || gs_idMainThread == kInvalidID ;
-}
-
#ifdef Yield
#undef Yield
#endif
g_numberOfThreads--;
-#ifdef __WXDEBUG__
m_critsect.Enter();
// check that the thread either exited or couldn't be created
}
m_critsect.Leave();
-#endif
wxDELETE( m_internal ) ;
}
{
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;
}
{
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") );
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);
// 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") );
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") );
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);
unsigned int wxThread::GetPriority() const
{
- wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
+ wxCriticalSectionLocker lock(const_cast<wxCriticalSection &>(m_critsect));
return m_internal->GetPriority();
}
unsigned long wxThread::GetId() const
{
- wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast
+ wxCriticalSectionLocker lock(const_cast<wxCriticalSection &>(m_critsect));
return (unsigned long)m_internal->GetId();
}
bool wxThreadModule::OnInit()
{
- bool hasThreadManager =
-#ifdef __LP64__
+ bool hasThreadManager =
+#ifdef __LP64__
true ; // TODO VERIFY IN NEXT BUILD
#else
MPLibraryIsLoaded();
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();
}
gs_critsectGui->Leave();
- delete gs_critsectGui;
- gs_critsectGui = NULL;
+ wxDELETE(gs_critsectGui);
}
- delete gs_critsectWaitingForGui;
- gs_critsectWaitingForGui = NULL;
+ wxDELETE(gs_critsectWaitingForGui);
}
// ----------------------------------------------------------------------------