X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/d01cc696fca6de1e1fa3ebcd10eefc6596d629f9..bbee1b4abc13379569607df8f6985ec68dc12231:/src/os2/thread.cpp diff --git a/src/os2/thread.cpp b/src/os2/thread.cpp index 04769f4cb2..c8cd9a7968 100644 --- a/src/os2/thread.cpp +++ b/src/os2/thread.cpp @@ -21,6 +21,9 @@ #include #include "wx/module.h" +#include "wx/intl.h" +#include "wx/utils.h" +#include "wx/log.h" #include "wx/thread.h" #define INCL_DOSSEMAPHORES @@ -53,21 +56,21 @@ wxMutex* p_wxMainMutex; wxThread* m_pThread; // pointer to the wxWindows thread object // if it's FALSE, some secondary thread is holding the GUI lock -static bool s_bGuiOwnedByMainThread = TRUE; +static bool gs_bGuiOwnedByMainThread = TRUE; // critical section which controls access to all GUI functions: any secondary // thread (i.e. except the main one) must enter this crit section before doing // any GUI calls -static wxCriticalSection *s_pCritsectGui = NULL; +static wxCriticalSection *gs_pCritsectGui = NULL; // critical section which protects s_nWaitingForGui variable -static wxCriticalSection *s_pCritsectWaitingForGui = NULL; +static wxCriticalSection *gs_pCritsectWaitingForGui = NULL; // number of threads waiting for GUI in wxMutexGuiEnter() -static size_t s_nWaitingForGui = 0; +static size_t gs_nWaitingForGui = 0; // are we waiting for a thread termination? -static bool s_bWaitingForThread = FALSE; +static bool gs_bWaitingForThread = FALSE; // ============================================================================ // OS/2 implementation of thread classes @@ -232,7 +235,7 @@ wxCondition::~wxCondition() void wxCondition::Wait() { - (void)m_internal->Wait(SEM_INFINITE_WAIT); + (void)m_internal->Wait(SEM_INDEFINITE_WAIT); } bool wxCondition::Wait( @@ -314,7 +317,9 @@ public: } // create a new (suspended) thread (for the given thread object) - bool Create(wxThread* pThread); + bool Create( wxThread* pThread + ,unsigned int uStackSize + ); // suspend/resume/terminate bool Suspend(); @@ -356,10 +361,10 @@ ULONG wxThreadInternal::OS2ThreadStart( // enter m_critsect before changing the thread state pThread->m_critsect.Enter(); - bool bWasCancelled = thread->m_internal->GetState() == STATE_CANCELED; + bool bWasCancelled = pThread->m_internal->GetState() == STATE_CANCELED; pThread->m_internal->SetState(STATE_EXITED); - thread->m_critsect.Leave(); + pThread->m_critsect.Leave(); pThread->OnExit(); @@ -368,7 +373,7 @@ ULONG wxThreadInternal::OS2ThreadStart( if (pThread->IsDetached() && !bWasCancelled) { // auto delete - delete thread; + delete pThread; } //else: the joinable threads handle will be closed when Wait() is done return dwRet; @@ -380,6 +385,7 @@ void wxThreadInternal::SetPriority( { // translate wxWindows priority to the PM one ULONG ulOS2_Priority; + ULONG ulrc; m_nPriority = nPriority; @@ -411,6 +417,7 @@ void wxThreadInternal::SetPriority( bool wxThreadInternal::Create( wxThread* pThread +, unsigned int uStackSize ) { APIRET ulrc; @@ -419,7 +426,7 @@ bool wxThreadInternal::Create( ,(PFNTHREAD)wxThreadInternal::OS2ThreadStart ,(ULONG)pThread ,CREATE_SUSPENDED | STACK_SPARSE - ,8192L + ,(ULONG)uStackSize ); if(ulrc != 0) { @@ -515,9 +522,11 @@ wxThread::~wxThread() // create/start thread // ------------------- -wxThreadError wxThread::Create() +wxThreadError wxThread::Create( + unsigned int uStackSize +) { - if ( !m_internal->Create(this) ) + if ( !m_internal->Create(this, uStackSize) ) return wxTHREAD_NO_RESOURCE; return wxTHREAD_NO_ERROR; @@ -582,7 +591,7 @@ wxThreadError wxThread::Delete(ExitCode *pRc) if (IsMain()) { // set flag for wxIsWaitingForThread() - gs_waitingForThread = TRUE; + gs_bWaitingForThread = TRUE; #if wxUSE_GUI wxBeginBusyCursor(); @@ -596,73 +605,22 @@ wxThreadError wxThread::Delete(ExitCode *pRc) } #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 - ULONG ulrc; - do - { - ulrc = ::MsgWaitForMultipleObjects - ( - 1, // number of objects to wait for - &hThread, // the objects - FALSE, // don't wait for all objects - INFINITE, // no timeout - QS_ALLEVENTS // return as soon as there are any events - ); - - switch ( result ) - { - case 0xFFFFFFFF: - // error - wxLogSysError(_("Can not wait for thread termination")); - Kill(); - return wxTHREAD_KILLED; - - case WAIT_OBJECT_0: - // thread we're waiting for terminated - break; - - case WAIT_OBJECT_0 + 1: - // new message arrived, process it - if ( !wxTheApp->DoMessage() ) - { - // WM_QUIT received: kill the thread - Kill(); - - return wxTHREAD_KILLED; - } - - if ( IsMain() ) - { - // give the thread we're waiting for chance to exit - // from the GUI call it might have been in - if ( (gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread() ) - { - wxMutexGuiLeave(); - } - } - - break; - - default: - 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 ) + // need a way to finish GUI processing before killing the thread + // until then we just exit + + if ((gs_nWaitingForGui > 0) && wxGuiOwnedByMainThread()) { - wxFAIL_MSG(wxT("unexpected result of WaitForSingleObject")); + wxMutexGuiLeave(); } +#else // !wxUSE_GUI + + // can't wait for yourself to end under OS/2 so just quit + #endif // wxUSE_GUI/!wxUSE_GUI if ( IsMain() ) { - gs_waitingForThread = FALSE; + gs_bWaitingForThread = FALSE; #if wxUSE_GUI wxEndBusyCursor(); @@ -670,25 +628,13 @@ wxThreadError wxThread::Delete(ExitCode *pRc) } } - if ( !::GetExitCodeThread(hThread, (LPDWORD)&rc) ) - { - wxLogLastError("GetExitCodeThread"); - - rc = (ExitCode)-1; - } - - if ( IsDetached() ) + ::DosExit(0, 0); + // probably won't get this far, but + if (IsDetached()) { - // if the thread exits normally, this is done in WinThreadStart, but in - // this case it would have been too early because - // MsgWaitForMultipleObject() would fail if the therad handle was - // closed while we were waiting on it, so we must do it here delete this; } - wxASSERT_MSG( (DWORD)rc != STILL_ACTIVE, - wxT("thread must be already terminated.") ); - if ( pRc ) *pRc = rc; @@ -701,14 +647,19 @@ wxThreadError wxThread::Kill() return wxTHREAD_NOT_RUNNING; ::DosKillThread(m_internal->GetHandle()); - delete this; + m_internal->Free(); + if (IsDetached()) + { + delete this; + } return wxTHREAD_NO_ERROR; } void wxThread::Exit( - void* pStatus + ExitCode pStatus ) { + m_internal->Free(); delete this; ::DosExit(EXIT_THREAD, ULONG(pStatus)); wxFAIL_MSG(wxT("Couldn't return from DosExit()!")); @@ -730,11 +681,18 @@ unsigned int wxThread::GetPriority() const return m_internal->GetPriority(); } +unsigned long wxThread::GetId() const +{ + wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); // const_cast + + return (unsigned long)m_internal->GetId(); +} + bool wxThread::IsRunning() const { wxCriticalSectionLocker lock((wxCriticalSection &)m_critsect); - return m_internal->GetState() == STATE_RUNNING; + return(m_internal->GetState() == STATE_RUNNING); } bool wxThread::IsAlive() const @@ -759,11 +717,6 @@ bool wxThread::TestDestroy() return m_internal->GetState() == STATE_CANCELED; } -wxThread::~wxThread() -{ - delete m_internal; -} - // ---------------------------------------------------------------------------- // Automatic initialization for thread module // ---------------------------------------------------------------------------- @@ -782,10 +735,10 @@ IMPLEMENT_DYNAMIC_CLASS(wxThreadModule, wxModule) bool wxThreadModule::OnInit() { - s_pCritsectWaitingForGui = new wxCriticalSection(); + gs_pCritsectWaitingForGui = new wxCriticalSection(); - s_pCritsectGui = new wxCriticalSection(); - s_pCritsectGui->Enter(); + gs_pCritsectGui = new wxCriticalSection(); + gs_pCritsectGui->Enter(); PTIB ptib; PPIB ppib; @@ -798,14 +751,18 @@ bool wxThreadModule::OnInit() void wxThreadModule::OnExit() { - if (s_pCritsectGui) + if (gs_pCritsectGui) { - s_pCritsectGui->Leave(); - delete s_pCritsectGui; - s_pCritsectGui = NULL; + gs_pCritsectGui->Leave(); +#if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) + delete gs_pCritsectGui; +#endif + gs_pCritsectGui = NULL; } - wxDELETE(s_pCritsectWaitingForGui); +#if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 ))) + wxDELETE(gs_pCritsectWaitingForGui); +#endif } // ---------------------------------------------------------------------------- @@ -819,24 +776,24 @@ void WXDLLEXPORT wxWakeUpMainThread() void WXDLLEXPORT wxMutexGuiLeave() { - wxCriticalSectionLocker enter(*s_pCritsectWaitingForGui); + wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui); if ( wxThread::IsMain() ) { - s_bGuiOwnedByMainThread = FALSE; + gs_bGuiOwnedByMainThread = FALSE; } else { // decrement the number of waiters now - wxASSERT_MSG( s_nWaitingForGui > 0, + wxASSERT_MSG(gs_nWaitingForGui > 0, wxT("calling wxMutexGuiLeave() without entering it first?") ); - s_nWaitingForGui--; + gs_nWaitingForGui--; wxWakeUpMainThread(); } - s_pCritsectGui->Leave(); + gs_pCritsectGui->Leave(); } void WXDLLEXPORT wxMutexGuiLeaveOrEnter() @@ -844,17 +801,17 @@ void WXDLLEXPORT wxMutexGuiLeaveOrEnter() wxASSERT_MSG( wxThread::IsMain(), wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") ); - wxCriticalSectionLocker enter(*s_pCritsectWaitingForGui); + wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui); - if ( s_nWaitingForGui == 0 ) + if (gs_nWaitingForGui == 0) { // no threads are waiting for GUI - so we may acquire the lock without // any danger (but only if we don't already have it) if (!wxGuiOwnedByMainThread()) { - s_pCritsectGui->Enter(); + gs_pCritsectGui->Enter(); - s_bGuiOwnedByMainThread = TRUE; + gs_bGuiOwnedByMainThread = TRUE; } //else: already have it, nothing to do } @@ -871,12 +828,12 @@ void WXDLLEXPORT wxMutexGuiLeaveOrEnter() bool WXDLLEXPORT wxGuiOwnedByMainThread() { - return s_bGuiOwnedByMainThread; + return gs_bGuiOwnedByMainThread; } bool WXDLLEXPORT wxIsWaitingForThread() { - return s_bWaitingForThread; + return gs_bWaitingForThread; } #endif