+bool wxThreadModule::OnInit()
+{
+ gs_pCritsectWaitingForGui = new wxCriticalSection();
+
+ gs_pCritsectGui = new wxCriticalSection();
+ gs_pCritsectGui->Enter();
+
+ PTIB ptib;
+ PPIB ppib;
+
+ ::DosGetInfoBlocks(&ptib, &ppib);
+
+ s_ulIdMainThread = ptib->tib_ptib2->tib2_ultid;
+ return TRUE;
+}
+
+void wxThreadModule::OnExit()
+{
+ if (gs_pCritsectGui)
+ {
+ gs_pCritsectGui->Leave();
+#if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 )))
+ delete gs_pCritsectGui;
+#endif
+ gs_pCritsectGui = NULL;
+ }
+
+#if (!(defined(__VISAGECPP__) && (__IBMCPP__ < 400 || __IBMC__ < 400 )))
+ wxDELETE(gs_pCritsectWaitingForGui);
+#endif
+}
+
+// ----------------------------------------------------------------------------
+// Helper functions
+// ----------------------------------------------------------------------------
+
+// wake up the main thread if it's in ::GetMessage()
+void WXDLLEXPORT wxWakeUpMainThread()
+{
+ if ( !::WinPostQueueMsg(wxTheApp->m_hMq, WM_NULL, 0, 0) )
+ {
+ // should never happen
+ wxLogLastError(wxT("WinPostMessage(WM_NULL)"));
+ }
+}
+
+void WXDLLEXPORT wxMutexGuiEnter()
+{
+ // this would dead lock everything...
+ wxASSERT_MSG( !wxThread::IsMain(),
+ wxT("main thread doesn't want to block in wxMutexGuiEnter()!") );
+
+ // the order in which we enter the critical sections here is crucial!!
+
+ // set the flag telling to the main thread that we want to do some GUI
+ {
+ wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui);
+
+ gs_nWaitingForGui++;
+ }
+
+ wxWakeUpMainThread();
+
+ // now we may block here because the main thread will soon let us in
+ // (during the next iteration of OnIdle())
+ gs_pCritsectGui->Enter();
+}
+
+void WXDLLEXPORT wxMutexGuiLeave()
+{
+ wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui);
+
+ if ( wxThread::IsMain() )
+ {
+ gs_bGuiOwnedByMainThread = FALSE;
+ }
+ else
+ {
+ // decrement the number of waiters now
+ wxASSERT_MSG(gs_nWaitingForGui > 0,
+ wxT("calling wxMutexGuiLeave() without entering it first?") );
+
+ gs_nWaitingForGui--;
+
+ wxWakeUpMainThread();
+ }
+
+ gs_pCritsectGui->Leave();
+}
+
+void WXDLLEXPORT wxMutexGuiLeaveOrEnter()
+{
+ wxASSERT_MSG( wxThread::IsMain(),
+ wxT("only main thread may call wxMutexGuiLeaveOrEnter()!") );
+
+ wxCriticalSectionLocker enter(*gs_pCritsectWaitingForGui);
+
+ 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())
+ {
+ gs_pCritsectGui->Enter();
+
+ gs_bGuiOwnedByMainThread = TRUE;
+ }
+ //else: already have it, nothing to do
+ }
+ else
+ {
+ // some threads are waiting, release the GUI lock if we have it
+ if (wxGuiOwnedByMainThread())
+ {
+ wxMutexGuiLeave();
+ }
+ //else: some other worker thread is doing GUI
+ }
+}
+
+bool WXDLLEXPORT wxGuiOwnedByMainThread()
+{
+ return gs_bGuiOwnedByMainThread;
+}
+
+bool WXDLLEXPORT wxIsWaitingForThread()
+{
+ return gs_bWaitingForThread;
+}
+
+// ----------------------------------------------------------------------------
+// include common implementation code
+// ----------------------------------------------------------------------------
+
+#include "wx/thrimpl.cpp"
+