X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/401eb3dec29c09b9afcc843842cba48b33a5089b..222702b112dcc7bebe018d6f4d66fe469fefd02c:/src/unix/threadpsx.cpp diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index 47e9a41e62..e8aad25e50 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -21,11 +21,12 @@ // headers // ---------------------------------------------------------------------------- -#ifdef __GNUG__ +#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA) #pragma implementation "thread.h" #endif -#include "wx/defs.h" +// for compilers that support precompilation, includes "wx.h". +#include "wx/wxprec.h" #if wxUSE_THREADS @@ -36,6 +37,7 @@ #include "wx/intl.h" #include "wx/dynarray.h" #include "wx/timer.h" +#include "wx/stopwatch.h" #include #include @@ -58,6 +60,12 @@ #include #endif +#ifdef __VMS + #define THR_ID(thr) ((long long)(thr)->GetId()) +#else + #define THR_ID(thr) ((long)(thr)->GetId()) +#endif + // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -106,7 +114,7 @@ WX_DEFINE_ARRAY(wxThread *, wxArrayThread); static wxArrayThread gs_allThreads; // the id of the main thread -static pthread_t gs_tidMain; +static pthread_t gs_tidMain = (pthread_t)-1; // the key for the pointer to the associated wxThread object static pthread_key_t gs_keySelf; @@ -122,10 +130,10 @@ static wxMutex *gs_mutexDeleteThread = (wxMutex *)NULL; // gs_nThreadsBeingDeleted will have been deleted static wxCondition *gs_condAllDeleted = (wxCondition *)NULL; -#if wxUSE_GUI - // this mutex must be acquired before any call to a GUI function - static wxMutex *gs_mutexGui; -#endif // wxUSE_GUI +// 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 +// of wxBase) +static wxMutex *gs_mutexGui = NULL; // when we wait for a thread to exit, we're blocking on a condition which the // thread signals in its SignalExit() method -- but this condition can't be a @@ -166,6 +174,12 @@ private: 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; @@ -488,15 +502,15 @@ wxSemaError wxSemaphoreInternal::Wait() while ( m_count == 0 ) { wxLogTrace(TRACE_SEMA, - "Thread %ld waiting for semaphore to become signalled", + _T("Thread %ld waiting for semaphore to become signalled"), wxThread::GetCurrentId()); if ( m_cond.Wait() != wxCOND_NO_ERROR ) return wxSEMA_MISC_ERROR; wxLogTrace(TRACE_SEMA, - "Thread %ld finished waiting for semaphore, count = %u", - wxThread::GetCurrentId(), m_count); + _T("Thread %ld finished waiting for semaphore, count = %lu"), + wxThread::GetCurrentId(), (unsigned long)m_count); } m_count--; @@ -532,8 +546,17 @@ wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds) return wxSEMA_TIMEOUT; } - if ( m_cond.Wait(remainingTime) != wxCOND_NO_ERROR ) - return wxSEMA_MISC_ERROR; + switch ( m_cond.WaitTimeout(remainingTime) ) + { + case wxCOND_TIMEOUT: + return wxSEMA_TIMEOUT; + + default: + return wxSEMA_MISC_ERROR; + + case wxCOND_NO_ERROR: + ; + } } m_count--; @@ -553,9 +576,9 @@ wxSemaError wxSemaphoreInternal::Post() m_count++; wxLogTrace(TRACE_SEMA, - "Thread %ld about to signal semaphore, count = %u", - wxThread::GetCurrentId(), m_count); - + _T("Thread %ld about to signal semaphore, count = %lu"), + wxThread::GetCurrentId(), (unsigned long)m_count); + return m_cond.Signal() == wxCOND_NO_ERROR ? wxSEMA_NO_ERROR : wxSEMA_MISC_ERROR; } @@ -620,7 +643,7 @@ public: }; wxLogTrace(TRACE_THREADS, _T("Thread %ld: %s => %s."), - GetId(), stateNames[m_state], stateNames[state]); + (long)GetId(), stateNames[m_state], stateNames[state]); #endif // __WXDEBUG__ m_state = state; @@ -656,7 +679,7 @@ public: private: pthread_t m_threadId; // id of the thread 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; @@ -696,7 +719,7 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) { wxThreadInternal *pthread = thread->m_internal; - wxLogTrace(TRACE_THREADS, _T("Thread %ld started."), pthread->GetId()); + wxLogTrace(TRACE_THREADS, _T("Thread %ld started."), THR_ID(pthread)); // associate the thread pointer with the newly created thread so that // wxThread::This() will work @@ -733,13 +756,15 @@ void *wxThreadInternal::PthreadStart(wxThread *thread) if ( !dontRunAtAll ) { // call the main entry - wxLogTrace(TRACE_THREADS, _T("Thread %ld about to enter its Entry()."), - pthread->GetId()); + wxLogTrace(TRACE_THREADS, + _T("Thread %ld about to enter its Entry()."), + THR_ID(pthread)); pthread->m_exitcode = thread->Entry(); - wxLogTrace(TRACE_THREADS, _T("Thread %ld Entry() returned %lu."), - pthread->GetId(), (unsigned long)pthread->m_exitcode); + wxLogTrace(TRACE_THREADS, + _T("Thread %ld Entry() returned %lu."), + THR_ID(pthread), (unsigned long)pthread->m_exitcode); { wxCriticalSectionLocker lock(thread->m_critsect); @@ -849,7 +874,8 @@ void wxThreadInternal::Wait() wxMutexGuiLeave(); wxLogTrace(TRACE_THREADS, - _T("Starting to wait for thread %ld to exit."), GetId()); + _T("Starting to wait for thread %ld to exit."), + THR_ID(this)); // to avoid memory leaks we should call pthread_join(), but it must only be // done once so use a critical section to serialize the code below @@ -862,14 +888,13 @@ void wxThreadInternal::Wait() // we're cancelled inside pthread_join(), things will almost // certainly break - but if we disable the cancellation, we // might deadlock - if ( pthread_join((pthread_t)GetId(), &m_exitcode) != 0 ) + if ( pthread_join(GetId(), &m_exitcode) != 0 ) { // this is a serious problem, so use wxLogError and not // wxLogDebug: it is possible to bring the system to its knees // by creating too many threads and not joining them quite // easily - wxLogError(_("Failed to join a thread, potential memory leak " - "detected - please restart the program")); + wxLogError(_("Failed to join a thread, potential memory leak detected - please restart the program")); } m_shouldBeJoined = FALSE; @@ -888,7 +913,8 @@ void wxThreadInternal::Pause() wxCHECK_RET( m_state == STATE_PAUSED, wxT("thread must first be paused with wxThread::Pause().") ); - wxLogTrace(TRACE_THREADS, _T("Thread %ld goes to sleep."), GetId()); + wxLogTrace(TRACE_THREADS, + _T("Thread %ld goes to sleep."), THR_ID(this)); // wait until the semaphore is Post()ed from Resume() m_semSuspend.Wait(); @@ -903,7 +929,8 @@ void wxThreadInternal::Resume() // TestDestroy() since the last call to Pause() for example if ( IsReallyPaused() ) { - wxLogTrace(TRACE_THREADS, _T("Waking up thread %ld"), GetId()); + wxLogTrace(TRACE_THREADS, + _T("Waking up thread %ld"), THR_ID(this)); // wake up Pause() m_semSuspend.Post(); @@ -913,8 +940,8 @@ void wxThreadInternal::Resume() } else { - wxLogTrace(TRACE_THREADS, _T("Thread %ld is not yet really paused"), - GetId()); + wxLogTrace(TRACE_THREADS, + _T("Thread %ld is not yet really paused"), THR_ID(this)); } SetState(STATE_RUNNING); @@ -931,7 +958,7 @@ wxThread *wxThread::This() bool wxThread::IsMain() { - return (bool)pthread_equal(pthread_self(), gs_tidMain); + return (bool)pthread_equal(pthread_self(), gs_tidMain) || gs_tidMain == (pthread_t)-1; } void wxThread::Yield() @@ -943,7 +970,7 @@ void wxThread::Yield() void wxThread::Sleep(unsigned long milliseconds) { - wxUsleep(milliseconds); + wxMilliSleep(milliseconds); } int wxThread::GetCPUCount() @@ -960,8 +987,8 @@ int wxThread::GetCPUCount() wxString s; if ( file.ReadAll(&s) ) { - // (ab)use Replace() to find the number of "processor" strings - size_t count = s.Replace(_T("processor"), _T("")); + // (ab)use Replace() to find the number of "processor: num" strings + size_t count = s.Replace(_T("processor\t:"), _T("")); if ( count > 0 ) { return count; @@ -987,19 +1014,24 @@ int wxThread::GetCPUCount() return -1; } +// VMS is a 64 bit system and threads have 64 bit pointers. +// FIXME: also needed for other systems???? #ifdef __VMS - // VMS is a 64 bit system and threads have 64 bit pointers. - // ??? also needed for other systems???? unsigned long long wxThread::GetCurrentId() { return (unsigned long long)pthread_self(); -#else +} + +#else // !__VMS + unsigned long wxThread::GetCurrentId() { return (unsigned long)pthread_self(); -#endif } +#endif // __VMS/!__VMS + + bool wxThread::SetConcurrency(size_t level) { #ifdef HAVE_THR_SETCONCURRENCY @@ -1424,8 +1456,7 @@ wxThreadError wxThread::Kill() void wxThread::Exit(ExitCode status) { wxASSERT_MSG( This() == this, - _T("wxThread::Exit() can only be called in the " - "context of the same thread") ); + _T("wxThread::Exit() can only be called in the context of the same thread") ); if ( m_isDetached ) { @@ -1453,6 +1484,12 @@ void wxThread::Exit(ExitCode status) // only call one thread function at a time :-( DeleteThread(this); } + else + { + m_critsect.Enter(); + m_internal->SetState(STATE_EXITED); + m_critsect.Leave(); + } // terminate the thread (pthread_exit() never returns) pthread_exit(status); @@ -1464,8 +1501,7 @@ void wxThread::Exit(ExitCode status) bool wxThread::TestDestroy() { wxASSERT_MSG( This() == this, - _T("wxThread::TestDestroy() can only be called in the " - "context of the same thread") ); + _T("wxThread::TestDestroy() can only be called in the context of the same thread") ); m_critsect.Enter(); @@ -1498,8 +1534,7 @@ wxThread::~wxThread() if ( m_internal->GetState() != STATE_EXITED && m_internal->GetState() != STATE_NEW ) { - wxLogDebug(_T("The thread %ld is being destroyed although it is still " - "running! The application may crash."), GetId()); + wxLogDebug(_T("The thread %ld is being destroyed although it is still running! The application may crash."), GetId()); } m_critsect.Leave(); @@ -1565,19 +1600,15 @@ bool wxThreadModule::OnInit() int rc = pthread_key_create(&gs_keySelf, NULL /* dtor function */); if ( rc != 0 ) { - wxLogSysError(rc, _("Thread module initialization failed: " - "failed to create thread key")); + wxLogSysError(rc, _("Thread module initialization failed: failed to create thread key")); return FALSE; } gs_tidMain = pthread_self(); -#if wxUSE_GUI gs_mutexGui = new wxMutex(); - gs_mutexGui->Lock(); -#endif // wxUSE_GUI gs_mutexDeleteThread = new wxMutex(); gs_condAllDeleted = new wxCondition( *gs_mutexDeleteThread ); @@ -1598,8 +1629,9 @@ void wxThreadModule::OnExit() if ( nThreadsBeingDeleted > 0 ) { - wxLogTrace(TRACE_THREADS, _T("Waiting for %u threads to disappear"), - nThreadsBeingDeleted); + wxLogTrace(TRACE_THREADS, + _T("Waiting for %lu threads to disappear"), + (unsigned long)nThreadsBeingDeleted); // have to wait until all of them disappear gs_condAllDeleted->Wait(); @@ -1610,8 +1642,8 @@ void wxThreadModule::OnExit() size_t count = gs_allThreads.GetCount(); if ( count != 0u ) { - wxLogDebug(wxT("%u threads were not terminated by the application."), - count); + wxLogDebug(wxT("%lu threads were not terminated by the application."), + (unsigned long)count); } for ( size_t n = 0u; n < count; n++ ) @@ -1621,12 +1653,9 @@ void wxThreadModule::OnExit() gs_allThreads[0]->Delete(); } -#if wxUSE_GUI // destroy GUI mutex gs_mutexGui->Unlock(); - delete gs_mutexGui; -#endif // wxUSE_GUI // and free TLD slot (void)pthread_key_delete(gs_keySelf); @@ -1645,8 +1674,8 @@ static void ScheduleThreadForDeletion() gs_nThreadsBeingDeleted++; - wxLogTrace(TRACE_THREADS, _T("%u thread%s waiting to be deleted"), - gs_nThreadsBeingDeleted, + wxLogTrace(TRACE_THREADS, _T("%lu thread%s waiting to be deleted"), + (unsigned long)gs_nThreadsBeingDeleted, gs_nThreadsBeingDeleted == 1 ? "" : "s"); } @@ -1663,8 +1692,8 @@ static void DeleteThread(wxThread *This) wxCHECK_RET( gs_nThreadsBeingDeleted > 0, _T("no threads scheduled for deletion, yet we delete one?") ); - wxLogTrace(TRACE_THREADS, _T("%u scheduled for deletion threads left."), - gs_nThreadsBeingDeleted - 1); + wxLogTrace(TRACE_THREADS, _T("%lu scheduled for deletion threads left."), + (unsigned long)gs_nThreadsBeingDeleted - 1); if ( !--gs_nThreadsBeingDeleted ) { @@ -1675,16 +1704,12 @@ static void DeleteThread(wxThread *This) void wxMutexGuiEnter() { -#if wxUSE_GUI gs_mutexGui->Lock(); -#endif // wxUSE_GUI } void wxMutexGuiLeave() { -#if wxUSE_GUI gs_mutexGui->Unlock(); -#endif // wxUSE_GUI } // ----------------------------------------------------------------------------