X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fd91cec1417a06b5e0ee09b3e677da5cc73ea0a3..acd32ffcdb319f162633c20e0202db3f8542998a:/src/unix/threadpsx.cpp diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index a5fa470848..db3063e48e 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -27,8 +27,10 @@ #if wxUSE_THREADS #include "wx/thread.h" +#include "wx/except.h" #ifndef WX_PRECOMP + #include "wx/app.h" #include "wx/dynarray.h" #include "wx/intl.h" #include "wx/log.h" @@ -126,11 +128,11 @@ static pthread_key_t gs_keySelf; static size_t gs_nThreadsBeingDeleted = 0; // a mutex to protect gs_nThreadsBeingDeleted -static wxMutex *gs_mutexDeleteThread = (wxMutex *)NULL; +static wxMutex *gs_mutexDeleteThread = NULL; // and a condition variable which will be signaled when all // gs_nThreadsBeingDeleted will have been deleted -static wxCondition *gs_condAllDeleted = (wxCondition *)NULL; +static wxCondition *gs_condAllDeleted = NULL; // this mutex must be acquired before any call to a GUI function // (it's not inside #if wxUSE_GUI because this file is compiled as part @@ -176,6 +178,8 @@ private: private: pthread_mutex_t m_mutex; bool m_isOk; + wxMutexType m_type; + unsigned long m_owningThread; // wxConditionInternal uses our m_mutex friend class wxConditionInternal; @@ -190,6 +194,9 @@ extern "C" int pthread_mutexattr_settype(pthread_mutexattr_t *, int); wxMutexInternal::wxMutexInternal(wxMutexType mutexType) { + m_type = mutexType; + m_owningThread = 0; + int err; switch ( mutexType ) { @@ -250,11 +257,18 @@ wxMutexInternal::~wxMutexInternal() wxMutexError wxMutexInternal::Lock() { + if ((m_type == wxMUTEX_DEFAULT) && (m_owningThread != 0)) + { + if (m_owningThread == wxThread::GetCurrentId()) + return wxMUTEX_DEAD_LOCK; + } + return HandleLockResult(pthread_mutex_lock(&m_mutex)); } wxMutexError wxMutexInternal::Lock(unsigned long ms) { +#ifdef HAVE_PTHREAD_MUTEX_TIMEDLOCK static const long MSEC_IN_SEC = 1000; static const long NSEC_IN_MSEC = 1000000; static const long NSEC_IN_USEC = 1000; @@ -295,10 +309,17 @@ wxMutexError wxMutexInternal::Lock(unsigned long ms) } return HandleLockResult(pthread_mutex_timedlock(&m_mutex, &ts)); +#else // !HAVE_PTHREAD_MUTEX_TIMEDLOCK + wxUnusedVar(ms); + + return wxMUTEX_MISC_ERROR; +#endif // HAVE_PTHREAD_MUTEX_TIMEDLOCK/!HAVE_PTHREAD_MUTEX_TIMEDLOCK } wxMutexError wxMutexInternal::HandleLockResult(int err) { + // wxPrintf( "err %d\n", err ); + switch ( err ) { case EDEADLK: @@ -315,6 +336,8 @@ wxMutexError wxMutexInternal::HandleLockResult(int err) return wxMUTEX_TIMEOUT; case 0: + if (m_type == wxMUTEX_DEFAULT) + m_owningThread = wxThread::GetCurrentId(); return wxMUTEX_NO_ERROR; default: @@ -340,6 +363,8 @@ wxMutexError wxMutexInternal::TryLock() break; case 0: + if (m_type == wxMUTEX_DEFAULT) + m_owningThread = wxThread::GetCurrentId(); return wxMUTEX_NO_ERROR; default: @@ -351,6 +376,8 @@ wxMutexError wxMutexInternal::TryLock() wxMutexError wxMutexInternal::Unlock() { + m_owningThread = 0; + int err = pthread_mutex_unlock(&m_mutex); switch ( err ) { @@ -562,14 +589,14 @@ wxSemaError wxSemaphoreInternal::Wait() while ( m_count == 0 ) { wxLogTrace(TRACE_SEMA, - _T("Thread %ld waiting for semaphore to become signalled"), + _T("Thread %p waiting for semaphore to become signalled"), wxThread::GetCurrentId()); if ( m_cond.Wait() != wxCOND_NO_ERROR ) return wxSEMA_MISC_ERROR; wxLogTrace(TRACE_SEMA, - _T("Thread %ld finished waiting for semaphore, count = %lu"), + _T("Thread %p finished waiting for semaphore, count = %lu"), wxThread::GetCurrentId(), (unsigned long)m_count); } @@ -636,7 +663,7 @@ wxSemaError wxSemaphoreInternal::Post() m_count++; wxLogTrace(TRACE_SEMA, - _T("Thread %ld about to signal semaphore, count = %lu"), + _T("Thread %p about to signal semaphore, count = %lu"), wxThread::GetCurrentId(), (unsigned long)m_count); return m_cond.Signal() == wxCOND_NO_ERROR ? wxSEMA_NO_ERROR @@ -702,8 +729,8 @@ public: _T("EXITED"), }; - wxLogTrace(TRACE_THREADS, _T("Thread %ld: %s => %s."), - (long)GetId(), stateNames[m_state], stateNames[state]); + wxLogTrace(TRACE_THREADS, _T("Thread %p: %s => %s."), + GetId(), stateNames[m_state], stateNames[state]); #endif // __WXDEBUG__ m_state = state; @@ -779,7 +806,7 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) { wxThreadInternal *pthread = thread->m_internal; - wxLogTrace(TRACE_THREADS, _T("Thread %ld started."), THR_ID(pthread)); + wxLogTrace(TRACE_THREADS, _T("Thread %p started."), THR_ID(pthread)); // associate the thread pointer with the newly created thread so that // wxThread::This() will work @@ -817,14 +844,18 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) { // call the main entry wxLogTrace(TRACE_THREADS, - _T("Thread %ld about to enter its Entry()."), + _T("Thread %p about to enter its Entry()."), THR_ID(pthread)); - pthread->m_exitcode = thread->Entry(); + wxTRY + { + pthread->m_exitcode = thread->Entry(); - wxLogTrace(TRACE_THREADS, - _T("Thread %ld Entry() returned %lu."), - THR_ID(pthread), wxPtrToUInt(pthread->m_exitcode)); + wxLogTrace(TRACE_THREADS, + _T("Thread %p Entry() returned %lu."), + THR_ID(pthread), wxPtrToUInt(pthread->m_exitcode)); + } + wxCATCH_ALL( wxTheApp->OnUnhandledException(); ) { wxCriticalSectionLocker lock(thread->m_critsect); @@ -944,7 +975,7 @@ void wxThreadInternal::Wait() wxMutexGuiLeave(); wxLogTrace(TRACE_THREADS, - _T("Starting to wait for thread %ld to exit."), + _T("Starting to wait for thread %p to exit."), THR_ID(this)); // to avoid memory leaks we should call pthread_join(), but it must only be @@ -984,7 +1015,7 @@ void wxThreadInternal::Pause() wxT("thread must first be paused with wxThread::Pause().") ); wxLogTrace(TRACE_THREADS, - _T("Thread %ld goes to sleep."), THR_ID(this)); + _T("Thread %p goes to sleep."), THR_ID(this)); // wait until the semaphore is Post()ed from Resume() m_semSuspend.Wait(); @@ -1000,7 +1031,7 @@ void wxThreadInternal::Resume() if ( IsReallyPaused() ) { wxLogTrace(TRACE_THREADS, - _T("Waking up thread %ld"), THR_ID(this)); + _T("Waking up thread %p"), THR_ID(this)); // wake up Pause() m_semSuspend.Post(); @@ -1011,7 +1042,7 @@ void wxThreadInternal::Resume() else { wxLogTrace(TRACE_THREADS, - _T("Thread %ld is not yet really paused"), THR_ID(this)); + _T("Thread %p is not yet really paused"), THR_ID(this)); } SetState(STATE_RUNNING); @@ -1038,11 +1069,6 @@ void wxThread::Yield() #endif } -void wxThread::Sleep(unsigned long milliseconds) -{ - wxMilliSleep(milliseconds); -} - int wxThread::GetCPUCount() { #if defined(_SC_NPROCESSORS_ONLN) @@ -1305,7 +1331,7 @@ void wxThread::SetPriority(unsigned int prio) // map wx priorites WXTHREAD_MIN_PRIORITY..WXTHREAD_MAX_PRIORITY // to Unix priorities 20..-20 - if ( setpriority(PRIO_PROCESS, 0, -(2*prio)/5 + 20) == -1 ) + if ( setpriority(PRIO_PROCESS, 0, -(2*(int)prio)/5 + 20) == -1 ) { wxLogError(_("Failed to set thread priority %d."), prio); } @@ -1379,7 +1405,7 @@ wxThreadError wxThread::Resume() switch ( state ) { case STATE_PAUSED: - wxLogTrace(TRACE_THREADS, _T("Thread %ld suspended, resuming."), + wxLogTrace(TRACE_THREADS, _T("Thread %p suspended, resuming."), GetId()); m_internal->Resume(); @@ -1387,7 +1413,7 @@ wxThreadError wxThread::Resume() return wxTHREAD_NO_ERROR; case STATE_EXITED: - wxLogTrace(TRACE_THREADS, _T("Thread %ld exited, won't resume."), + wxLogTrace(TRACE_THREADS, _T("Thread %p exited, won't resume."), GetId()); return wxTHREAD_NO_ERROR; @@ -1536,7 +1562,11 @@ void wxThread::Exit(ExitCode status) // 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(); + wxTRY + { + OnExit(); + } + wxCATCH_ALL( wxTheApp->OnUnhandledException(); ) // delete C++ thread object if this is a detached thread - user is // responsible for doing this for joinable ones @@ -1767,14 +1797,14 @@ static void DeleteThread(wxThread *This) // or wxThreadModule::OnExit() would deadlock wxMutexLocker locker( *gs_mutexDeleteThread ); - wxLogTrace(TRACE_THREADS, _T("Thread %ld auto deletes."), This->GetId()); + wxLogTrace(TRACE_THREADS, _T("Thread %p auto deletes."), This->GetId()); delete This; wxCHECK_RET( gs_nThreadsBeingDeleted > 0, _T("no threads scheduled for deletion, yet we delete one?") ); - wxLogTrace(TRACE_THREADS, _T("%lu scheduled for deletion threads left."), + wxLogTrace(TRACE_THREADS, _T("%lu threads remain scheduled for deletion."), (unsigned long)gs_nThreadsBeingDeleted - 1); if ( !--gs_nThreadsBeingDeleted ) @@ -1784,12 +1814,12 @@ static void DeleteThread(wxThread *This) } } -void wxMutexGuiEnter() +void wxMutexGuiEnterImpl() { gs_mutexGui->Lock(); } -void wxMutexGuiLeave() +void wxMutexGuiLeaveImpl() { gs_mutexGui->Unlock(); }