X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3ef22a5b02ac7c963e767de1ace3f92e131a6d18..e3f9e20cb15c62bd347a8e52d2d36529adbdb3d6:/src/msw/thread.cpp diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index 0ac2427177..469ced786b 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -300,7 +300,7 @@ private: wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount) { -#ifndef __WXWINCE__ +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300) if ( maxcount == 0 ) { // make it practically infinite @@ -353,7 +353,7 @@ wxSemaError wxSemaphoreInternal::WaitTimeout(unsigned long milliseconds) wxSemaError wxSemaphoreInternal::Post() { -#ifndef __WXWINCE__ +#if !defined(_WIN32_WCE) || (_WIN32_WCE >= 300) if ( !::ReleaseSemaphore(m_semaphore, 1, NULL /* ptr to previous count */) ) #endif { @@ -484,7 +484,9 @@ THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param) // first of all, check whether we hadn't been cancelled already and don't // start the user code at all then - if ( thread->m_internal->GetState() == STATE_EXITED ) + bool isExited = (thread->m_internal->GetState() == STATE_EXITED); + + if ( isExited ) { rc = (THREAD_RETVAL)-1; } @@ -499,17 +501,23 @@ THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param) } rc = (THREAD_RETVAL)thread->Entry(); + } + + thread->OnExit(); + + // save IsDetached because thread object can be deleted by joinable + // threads after state is changed to STATE_EXITED. + bool isDetached = thread->IsDetached(); + if (!isExited) + { // enter m_critsect before changing the thread state wxCriticalSectionLocker lock(thread->m_critsect); - thread->m_internal->SetState(STATE_EXITED); } - thread->OnExit(); - // the thread may delete itself now if it wants, we don't need it any more - thread->m_internal->LetDie(); + if (isDetached) thread->m_internal->LetDie(); return rc; } @@ -690,7 +698,7 @@ wxThreadInternal::WaitForTerminate(wxCriticalSection& cs, // 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 + DWORD result wxDUMMY_INITIALIZE(0); do { if ( wxThread::IsMain() ) @@ -769,15 +777,24 @@ wxThreadInternal::WaitForTerminate(wxCriticalSection& cs, // although the thread might be already in the EXITED state it might not // have terminated yet and so we are not sure that it has actually // terminated if the "if" above hadn't been taken - do + for ( ;; ) { if ( !::GetExitCodeThread(m_hThread, (LPDWORD)&rc) ) { wxLogLastError(wxT("GetExitCodeThread")); rc = (wxThread::ExitCode)-1; + + break; } - } while ( (DWORD)rc == STILL_ACTIVE ); + + if ( (DWORD)rc != STILL_ACTIVE ) + break; + + // give the other thread some time to terminate, otherwise we may be + // starving it + ::Sleep(1); + } if ( pRc ) *pRc = rc; @@ -885,7 +902,7 @@ bool wxThread::SetConcurrency(size_t level) // get system affinity mask first HANDLE hProcess = ::GetCurrentProcess(); - DWORD dwProcMask, dwSysMask; + DWORD_PTR dwProcMask, dwSysMask; if ( ::GetProcessAffinityMask(hProcess, &dwProcMask, &dwSysMask) == 0 ) { wxLogLastError(_T("GetProcessAffinityMask")); @@ -966,7 +983,8 @@ bool wxThread::SetConcurrency(size_t level) return false; } -#endif +#endif // !__WXWINCE__ + return true; }