#endif
#ifndef WX_PRECOMP
-# include "wx/wx.h"
+ #include "wx/intl.h"
+ #include "wx/app.h"
#endif
#if wxUSE_THREADS
+#include "wx/apptrait.h"
+
#include "wx/msw/private.h"
#include "wx/msw/missing.h"
wxMutexError LockTimeout(DWORD milliseconds);
HANDLE m_mutex;
+
+ DECLARE_NO_COPY_CLASS(wxMutexInternal)
};
// all mutexes are recursive under Win32 so we don't use mutexType
{
if ( !::ReleaseMutex(m_mutex) )
{
- wxLogLastError(_("ReleaseMutex()"));
+ wxLogLastError(_T("ReleaseMutex()"));
return wxMUTEX_MISC_ERROR;
}
bool IsOk() const { return m_semaphore != NULL; }
wxSemaError Wait() { return WaitTimeout(INFINITE); }
- wxSemaError TryWait() { return WaitTimeout(0); }
+
+ wxSemaError TryWait()
+ {
+ wxSemaError rc = WaitTimeout(0);
+ if ( rc == wxSEMA_TIMEOUT )
+ rc = wxSEMA_BUSY;
+
+ return rc;
+ }
+
wxSemaError WaitTimeout(unsigned long milliseconds);
wxSemaError Post();
private:
HANDLE m_semaphore;
+
+ DECLARE_NO_COPY_CLASS(wxSemaphoreInternal)
};
wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
return wxSEMA_NO_ERROR;
case WAIT_TIMEOUT:
- return wxSEMA_BUSY;
+ return wxSEMA_TIMEOUT;
default:
wxLogLastError(_T("WaitForSingleObject(semaphore)"));
wxThreadState m_state; // state, see wxThreadState enum
unsigned int m_priority; // thread priority in "wx" units
DWORD m_tid; // thread id
+
+ DECLARE_NO_COPY_CLASS(wxThreadInternal)
};
THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param)
bool wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
{
+ wxASSERT_MSG( m_state == STATE_NEW && !m_hThread,
+ _T("Create()ing thread twice?") );
+
// for compilers which have it, we should use C RTL function for thread
// creation instead of Win32 API one because otherwise we will have memory
// leaks if the thread uses C RTL (and most threads do)
HANDLE hThread = m_internal->GetHandle();
- // Check if thread is really still running. There is a
- // race condition in WinThreadStart between the time the
- // m_internal->m_state is set to STATE_EXITED and the win32
- // thread actually exits. It can be flagged as STATE_EXITED
- // and then we don't wait for it to exit. This will cause
- // GetExitCodeThread to return STILL_ACTIVE.
- if ( !isRunning )
- {
- if ( !IsRunning() )
- {
- if ( ::GetExitCodeThread(hThread, (LPDWORD)&rc) )
- {
- if ((DWORD)rc == STILL_ACTIVE)
- isRunning = TRUE;
- }
- }
- else
- {
- isRunning = TRUE;
- }
- }
-
- // does it still run?
- if ( isRunning )
+ // does is still run?
+ if ( isRunning || IsRunning() )
{
if ( IsMain() )
{
m_internal->Cancel();
}
-#if wxUSE_GUI
// we can't just wait for the thread to terminate because it might be
// calling some GUI functions and so it will never terminate before we
// process the Windows messages that result from these functions
+ // (note that even in console applications we might have to process
+ // messages if we use wxExecute() or timers or ...)
DWORD result = 0; // suppress warnings from broken compilers
do
{
break;
case WAIT_OBJECT_0 + 1:
+ // new message arrived, process it
{
- MSG peekMsg;
- // Check if a new message has really arrived.
- // MsgWaitForMultipleObjects can indicate that a message
- // is ready for processing, but this message may be sucked
- // up by GetMessage and then GetMessage will hang and not
- // allow us to process the actual thread exit event.
- if (::PeekMessage(&peekMsg, (HWND) NULL, 0, 0, PM_NOREMOVE))
+ wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits()
+ : NULL;
+
+ if ( traits && !traits->DoMessageFromThreadWait() )
{
- // new message arrived, process it
- if ( !wxTheApp->DoMessage() )
- {
- // WM_QUIT received: kill the thread
- Kill();
-
- return wxTHREAD_KILLED;
- }
+ // WM_QUIT received: kill the thread
+ Kill();
+
+ return wxTHREAD_KILLED;
}
}
break;
wxFAIL_MSG(wxT("unexpected result of MsgWaitForMultipleObject"));
}
} while ( result != WAIT_OBJECT_0 );
-#else // !wxUSE_GUI
- // simply wait for the thread to terminate
- //
- // OTOH, even console apps create windows (in wxExecute, for WinSock
- // &c), so may be use MsgWaitForMultipleObject() too here?
- if ( WaitForSingleObject(hThread, INFINITE) != WAIT_OBJECT_0 )
- {
- wxFAIL_MSG(wxT("unexpected result of WaitForSingleObject"));
- }
-#endif // wxUSE_GUI/!wxUSE_GUI
if ( IsMain() )
{
// not a mutex, so the names are a bit confusing
// ----------------------------------------------------------------------------
-void WXDLLEXPORT wxMutexGuiEnter()
+void WXDLLIMPEXP_BASE wxMutexGuiEnter()
{
// this would dead lock everything...
wxASSERT_MSG( !wxThread::IsMain(),
gs_critsectGui->Enter();
}
-void WXDLLEXPORT wxMutexGuiLeave()
+void WXDLLIMPEXP_BASE wxMutexGuiLeave()
{
wxCriticalSectionLocker enter(*gs_critsectWaitingForGui);
gs_critsectGui->Leave();
}
-void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
+void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter()
{
wxASSERT_MSG( wxThread::IsMain(),
wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
}
}
-bool WXDLLEXPORT wxGuiOwnedByMainThread()
+bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread()
{
return gs_bGuiOwnedByMainThread;
}
// wake up the main thread if it's in ::GetMessage()
-void WXDLLEXPORT wxWakeUpMainThread()
+void WXDLLIMPEXP_BASE wxWakeUpMainThread()
{
// sending any message would do - hopefully WM_NULL is harmless enough
if ( !::PostThreadMessage(gs_idMainThread, WM_NULL, 0, 0) )
}
}
-bool WXDLLEXPORT wxIsWaitingForThread()
+bool WXDLLIMPEXP_BASE wxIsWaitingForThread()
{
return gs_waitingForThread;
}