X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/ed197fcf1572ba922802aaaa46e9f7970ea14bed..aacd14428971b5e199f88597f76a895c68dd298f:/src/mac/carbon/thread.cpp?ds=sidebyside diff --git a/src/mac/carbon/thread.cpp b/src/mac/carbon/thread.cpp index 289a8fa35e..cb8ecb4c2d 100644 --- a/src/mac/carbon/thread.cpp +++ b/src/mac/carbon/thread.cpp @@ -10,7 +10,7 @@ // Licence: wxWindows licence ///////////////////////////////////////////////////////////////////////////// -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "thread.h" #endif @@ -40,7 +40,7 @@ #else #include #include -#include +#include "wx/math.h" #endif #include "wx/mac/uma.h" #endif @@ -114,16 +114,40 @@ MPCriticalRegionID gs_guiCritical = kInvalidID; to use two indices one for each 32 bit part as the MP implementation is limited to longs. - I have two implementations for mutexes : + I have three implementations for mutexes : version A based on a binary semaphore, problem - not reentrant, version B based on a critical region, allows for reentrancy, performance implications not - yet tested + yet tested, and third a plain pthreads implementation The same for condition internal, one implementation by Aj Lavin and the other one copied from the thrimpl.cpp which I assume has been more broadly tested, I've just replaced the interlock increment with the appropriate PPC calls */ +// ---------------------------------------------------------------------------- +// wxCriticalSection +// ---------------------------------------------------------------------------- + +wxCriticalSection::wxCriticalSection() +{ + MPCreateCriticalRegion( (MPCriticalRegionID*) &m_critRegion ) ; +} + +wxCriticalSection::~wxCriticalSection() +{ + MPDeleteCriticalRegion( (MPCriticalRegionID) m_critRegion ) ; +} + +void wxCriticalSection::Enter() +{ + MPEnterCriticalRegion( (MPCriticalRegionID) m_critRegion , kDurationForever ) ; +} + +void wxCriticalSection::Leave() +{ + MPExitCriticalRegion((MPCriticalRegionID) m_critRegion ) ; +} + // ---------------------------------------------------------------------------- // wxMutex implementation // ---------------------------------------------------------------------------- @@ -962,7 +986,7 @@ private: MPQueueID m_notifyQueueId; // its notification queue wxThreadState m_state; // see wxThreadState enum - int m_prio; // in wxWindows units: from 0 to 100 + int m_prio; // in wxWidgets units: from 0 to 100 // this flag is set when the thread should terminate bool m_cancelled; @@ -1092,8 +1116,8 @@ void wxThreadInternal::SetPriority( int priority) if ( m_tid) { // Mac priorities range from 1 to 10,000, with a default of 100. - // wxWindows priorities range from 0 to 100 with a default of 50. - // We can map wxWindows to Mac priorities easily by assuming + // wxWidgets priorities range from 0 to 100 with a default of 50. + // We can map wxWidgets to Mac priorities easily by assuming // the former uses a logarithmic scale. const unsigned int macPriority = ( int)( exp( priority / 25.0 * log( 10.0)) + 0.5); @@ -1121,7 +1145,15 @@ void wxThreadInternal::Wait() // if the thread we're waiting for is waiting for the GUI mutex, we will // deadlock so make sure we release it temporarily if ( wxThread::IsMain() ) - wxMutexGuiLeave(); + { + // give the thread we're waiting for chance to do the GUI call + // it might be in, we don't do this conditionally as the to be waited on + // thread might have to acquire the mutex later but before terminating + if ( wxGuiOwnedByMainThread() ) + { + wxMutexGuiLeave(); + } + } { wxCriticalSectionLocker lock(m_csJoinFlag); @@ -1139,7 +1171,7 @@ void wxThreadInternal::Wait() kDurationForever); if ( err) { - wxLogSysError( _( "Cannot wait on thread to exit.")); + wxLogSysError( _( "Cannot wait for thread termination.")); rc = (void*) -1; } @@ -1150,10 +1182,6 @@ void wxThreadInternal::Wait() m_shouldBeJoined = FALSE; } } - - // reacquire GUI mutex - if ( wxThread::IsMain() ) - wxMutexGuiEnter(); } void wxThreadInternal::Pause() @@ -1197,7 +1225,7 @@ wxThread *wxThread::This() bool wxThread::IsMain() { - return GetCurrentId() == gs_idMainThread; + return GetCurrentId() == gs_idMainThread || gs_idMainThread == kInvalidID ; } #ifdef Yield @@ -1408,7 +1436,6 @@ wxThreadError wxThread::Delete(ExitCode *rc) *rc = m_internal->GetExitCode(); } } - //else: can't wait for detached threads } return wxTHREAD_NO_ERROR; @@ -1465,7 +1492,7 @@ void wxThread::Exit(ExitCode status) // m_critsect on us (almost all of them do) OnExit(); - MPTerminateTask( m_internal->GetId() , (long) status) ; + MPTaskID threadid = m_internal->GetId() ; if ( IsDetached() ) { @@ -1477,6 +1504,7 @@ void wxThread::Exit(ExitCode status) wxCriticalSectionLocker lock(m_critsect); m_internal->SetState(STATE_EXITED); } + MPTerminateTask( threadid , (long) status) ; } // also test whether we were paused @@ -1610,7 +1638,7 @@ bool wxThreadModule::OnInit() verify_noerr( MPAllocateTaskStorageIndex( &gs_tlsForWXThread ) ) ; // main thread's This() is NULL - verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , NULL ) ) ; + verify_noerr( MPSetTaskStorageValue( gs_tlsForWXThread , 0 ) ) ; gs_idMainThread = wxThread::GetCurrentId() ; @@ -1626,6 +1654,11 @@ void wxThreadModule::OnExit() { if ( gs_critsectGui ) { + if ( !wxGuiOwnedByMainThread() ) + { + gs_critsectGui->Enter(); + gs_bGuiOwnedByMainThread = true; + } gs_critsectGui->Leave(); delete gs_critsectGui; gs_critsectGui = NULL; @@ -1688,6 +1721,9 @@ 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 )