#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"
#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
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:
m_mutex = ::CreateMutex
(
NULL, // default secutiry attributes
- false, // not initially locked
+ FALSE, // not initially locked
NULL // no name
);
}
}
+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);
break;
case WAIT_TIMEOUT:
- return wxMUTEX_BUSY;
+ return wxMUTEX_TIMEOUT;
case WAIT_ABANDONED: // checked for above
default:
{
#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
}
// ----------------------------------------------------------------------------
// 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() )
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) )
{
return rc;
}
+/* static */
THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param)
{
THREAD_RETVAL rc = (THREAD_RETVAL)-1;
// 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.
}
}
-#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 )
{
// 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
// 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;
#include "wx/thrimpl.cpp"
#endif // wxUSE_THREADS
-