X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d3f8206ce7a28751edbe0610dcd40d54ac6d758d..91a6c655582321b61a7545ed9c121ad6593ccbfe:/src/msw/thread.cpp diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index 9a0bdbb46c..6b835a9707 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -21,13 +21,16 @@ #pragma hdrstop #endif +#if wxUSE_THREADS + +#include "wx/thread.h" + #ifndef WX_PRECOMP #include "wx/intl.h" #include "wx/app.h" + #include "wx/module.h" #endif -#if wxUSE_THREADS - #include "wx/apptrait.h" #include "wx/scopeguard.h" @@ -36,8 +39,6 @@ #include "wx/msw/seh.h" #include "wx/except.h" -#include "wx/module.h" -#include "wx/thread.h" // must have this symbol defined to get _beginthread/_endthread declarations #ifndef _MT @@ -177,7 +178,8 @@ public: bool IsOk() const { return m_mutex != NULL; } wxMutexError Lock() { return LockTimeout(INFINITE); } - wxMutexError TryLock() { return LockTimeout(0); } + wxMutexError Lock(unsigned long ms) { return LockTimeout(ms); } + wxMutexError TryLock(); wxMutexError Unlock(); private: @@ -195,7 +197,7 @@ wxMutexInternal::wxMutexInternal(wxMutexType WXUNUSED(mutexType)) m_mutex = ::CreateMutex ( NULL, // default secutiry attributes - false, // not initially locked + FALSE, // not initially locked NULL // no name ); @@ -216,6 +218,14 @@ wxMutexInternal::~wxMutexInternal() } } +wxMutexError wxMutexInternal::TryLock() +{ + const wxMutexError rc = LockTimeout(0); + + // we have a special return code for timeout in this case + return rc == wxMUTEX_TIMEOUT ? wxMUTEX_BUSY : rc; +} + wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds) { DWORD rc = ::WaitForSingleObject(m_mutex, milliseconds); @@ -236,7 +246,7 @@ wxMutexError wxMutexInternal::LockTimeout(DWORD milliseconds) break; case WAIT_TIMEOUT: - return wxMUTEX_BUSY; + return wxMUTEX_TIMEOUT; case WAIT_ABANDONED: // checked for above default: @@ -354,14 +364,22 @@ wxSemaError wxSemaphoreInternal::Post() { #if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300) if ( !::ReleaseSemaphore(m_semaphore, 1, NULL /* ptr to previous count */) ) -#endif { - wxLogLastError(_T("ReleaseSemaphore")); - - return wxSEMA_MISC_ERROR; + if ( GetLastError() == ERROR_TOO_MANY_POSTS ) + { + return wxSEMA_OVERFLOW; + } + else + { + wxLogLastError(_T("ReleaseSemaphore")); + return wxSEMA_MISC_ERROR; + } } return wxSEMA_NO_ERROR; +#else + return wxSEMA_MISC_ERROR; +#endif } // ---------------------------------------------------------------------------- @@ -436,6 +454,10 @@ public: // really start the thread (if it's not already dead) static THREAD_RETVAL DoThreadStart(wxThread *thread); + // call OnExit() on the thread + static void DoThreadOnExit(wxThread *thread); + + void KeepAlive() { if ( m_thread->IsDetached() ) @@ -477,14 +499,25 @@ private: wxThreadInternal& m_thrImpl; }; +/* static */ +void wxThreadInternal::DoThreadOnExit(wxThread *thread) +{ + wxTRY + { + thread->OnExit(); + } + wxCATCH_ALL( wxTheApp->OnUnhandledException(); ) +} + +/* static */ THREAD_RETVAL wxThreadInternal::DoThreadStart(wxThread *thread) { + wxON_BLOCK_EXIT1(DoThreadOnExit, thread); + THREAD_RETVAL rc = (THREAD_RETVAL)-1; wxTRY { - wxON_BLOCK_EXIT_OBJ0(*thread, wxThread::OnExit); - // store the thread object in the TLS if ( !::TlsSetValue(gs_tlsThisThread, thread) ) { @@ -500,6 +533,7 @@ THREAD_RETVAL wxThreadInternal::DoThreadStart(wxThread *thread) return rc; } +/* static */ THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param) { THREAD_RETVAL rc = (THREAD_RETVAL)-1; @@ -513,14 +547,16 @@ THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param) // start the user code at all then const bool hasExited = thread->m_internal->GetState() == STATE_EXITED; - if ( !hasExited ) + // run the thread function itself inside a SEH try/except block + wxSEH_TRY { - wxSEH_TRY - { + if ( hasExited ) + DoThreadOnExit(thread); + else rc = DoThreadStart(thread); - } - wxSEH_HANDLE((THREAD_RETVAL)-1) } + wxSEH_HANDLE((THREAD_RETVAL)-1) + // save IsDetached because thread object can be deleted by joinable // threads after state is changed to STATE_EXITED. @@ -725,18 +761,16 @@ wxThreadInternal::WaitForTerminate(wxCriticalSection& cs, } } -#if !defined(QS_ALLPOSTMESSAGE) -#define QS_ALLPOSTMESSAGE 0 -#endif - - result = ::MsgWaitForMultipleObjects - ( - 1, // number of objects to wait for - &m_hThread, // the objects - false, // don't wait for all objects - INFINITE, // no timeout - QS_ALLINPUT|QS_ALLPOSTMESSAGE // return as soon as there are any events - ); + wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL; + if ( traits ) + { + result = traits->WaitForThread(m_hThread); + } + else // can't wait for the thread + { + // so kill it below + result = 0xFFFFFFFF; + } switch ( result ) { @@ -761,9 +795,6 @@ wxThreadInternal::WaitForTerminate(wxCriticalSection& cs, // the system might dead lock then if ( wxThread::IsMain() ) { - wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() - : NULL; - if ( traits && !traits->DoMessageFromThreadWait() ) { // WM_QUIT received: kill the thread @@ -965,7 +996,7 @@ bool wxThread::SetConcurrency(size_t WXUNUSED_IN_WINCE(level)) // set it: we can't link to SetProcessAffinityMask() because it doesn't // exist in Win9x, use RT binding instead - typedef BOOL (*SETPROCESSAFFINITYMASK)(HANDLE, DWORD); + typedef BOOL (WINAPI *SETPROCESSAFFINITYMASK)(HANDLE, DWORD_PTR); // can use static var because we're always in the main thread here static SETPROCESSAFFINITYMASK pfnSetProcessAffinityMask = NULL; @@ -1363,4 +1394,3 @@ bool WXDLLIMPEXP_BASE wxIsWaitingForThread() #include "wx/thrimpl.cpp" #endif // wxUSE_THREADS -