]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/thread.cpp
Fix duplicate wxContextMenuEvent generation in wxMSW.
[wxWidgets.git] / src / msw / thread.cpp
index 1a668976f3f4d9597fbf527c15af06b6ae9de154..90d47a663e6939cca4bf64451bf4daffc7a55554 100644 (file)
@@ -40,6 +40,8 @@
 
 #include "wx/except.h"
 
+#include "wx/dynlib.h"
+
 // must have this symbol defined to get _beginthread/_endthread declarations
 #ifndef _MT
     #define _MT
@@ -62,7 +64,7 @@
 #if defined(__VISUALC__) || \
     (defined(__BORLANDC__) && (__BORLANDC__ >= 0x500)) || \
     (defined(__GNUG__) && defined(__MSVCRT__)) || \
-    defined(__WATCOMC__) || defined(__MWERKS__)
+    defined(__WATCOMC__)
 
 #ifndef __WXWINCE__
     #undef wxUSE_BEGIN_THREAD
@@ -163,6 +165,25 @@ void wxCriticalSection::Enter()
     ::EnterCriticalSection((CRITICAL_SECTION *)m_buffer);
 }
 
+bool wxCriticalSection::TryEnter()
+{
+#if wxUSE_DYNLIB_CLASS
+    typedef BOOL
+      (WINAPI *TryEnterCriticalSection_t)(LPCRITICAL_SECTION lpCriticalSection);
+
+    static TryEnterCriticalSection_t
+        pfnTryEnterCriticalSection = (TryEnterCriticalSection_t)
+            wxDynamicLibrary(wxT("kernel32.dll")).
+                GetSymbol(wxT("TryEnterCriticalSection"));
+
+    return pfnTryEnterCriticalSection
+            ? (*pfnTryEnterCriticalSection)((CRITICAL_SECTION *)m_buffer) != 0
+            : false;
+#else
+    return false;
+#endif
+}
+
 void wxCriticalSection::Leave()
 {
     ::LeaveCriticalSection((CRITICAL_SECTION *)m_buffer);
@@ -421,7 +442,7 @@ public:
         m_thread = thread;
         m_hThread = 0;
         m_state = STATE_NEW;
-        m_priority = WXTHREAD_DEFAULT_PRIORITY;
+        m_priority = wxPRIORITY_DEFAULT;
         m_nRef = 1;
     }
 
@@ -450,6 +471,7 @@ public:
     // (politely, this is not Kill()!) to do it
     wxThreadError WaitForTerminate(wxCriticalSection& cs,
                                    wxThread::ExitCode *pRc,
+                                   wxThreadWait waitMode,
                                    wxThread *threadToDelete = NULL);
 
     // kill the thread unconditionally
@@ -545,7 +567,7 @@ THREAD_RETVAL wxThreadInternal::DoThreadStart(wxThread *thread)
         // store the thread object in the TLS
         if ( !::TlsSetValue(gs_tlsThisThread, thread) )
         {
-            wxLogSysError(_("Can not start thread: error writing TLS."));
+            wxLogSysError(_("Cannot start thread: error writing TLS."));
 
             return THREAD_ERROR_EXIT;
         }
@@ -567,9 +589,14 @@ THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param)
     // each thread has its own SEH translator so install our own a.s.a.p.
     DisableAutomaticSETranslator();
 
+    // NB: Notice that we can't use wxCriticalSectionLocker in this function as
+    //     we use SEH and it's incompatible with C++ object dtors.
+
     // first of all, check whether we hadn't been cancelled already and don't
     // start the user code at all then
+    thread->m_critsect.Enter();
     const bool hasExited = thread->m_internal->GetState() == STATE_EXITED;
+    thread->m_critsect.Leave();
 
     // run the thread function itself inside a SEH try/except block
     wxSEH_TRY
@@ -587,10 +614,6 @@ THREAD_RETVAL THREAD_CALLCONV wxThreadInternal::WinThreadStart(void *param)
     const bool isDetached = thread->IsDetached();
     if ( !hasExited )
     {
-        // enter m_critsect before changing the thread state
-        //
-        // NB: can't use wxCriticalSectionLocker here as we use SEH and it's
-        //     incompatible with C++ object dtors
         thread->m_critsect.Enter();
         thread->m_internal->SetState(STATE_EXITED);
         thread->m_critsect.Leave();
@@ -676,7 +699,7 @@ bool wxThreadInternal::Create(wxThread *thread, unsigned int stackSize)
         return false;
     }
 
-    if ( m_priority != WXTHREAD_DEFAULT_PRIORITY )
+    if ( m_priority != wxPRIORITY_DEFAULT )
     {
         SetPriority(m_priority);
     }
@@ -703,6 +726,7 @@ wxThreadError wxThreadInternal::Kill()
 wxThreadError
 wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
                                    wxThread::ExitCode *pRc,
+                                   wxThreadWait waitMode,
                                    wxThread *threadToDelete)
 {
     // prevent the thread C++ object from disappearing as long as we are using
@@ -761,7 +785,8 @@ wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
         Cancel();
     }
 
-    threadToDelete->OnDelete();
+    if ( threadToDelete )
+        threadToDelete->OnDelete();
 
     // now wait for thread to finish
     if ( wxThread::IsMain() )
@@ -791,7 +816,7 @@ wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
         wxAppTraits *traits = wxTheApp ? wxTheApp->GetTraits() : NULL;
         if ( traits )
         {
-            result = traits->WaitForThread(m_hThread);
+            result = traits->WaitForThread(m_hThread, waitMode);
         }
         else // can't wait for the thread
         {
@@ -803,7 +828,7 @@ wxThreadInternal::WaitForTerminate(wxCriticalSection& cs,
         {
             case 0xFFFFFFFF:
                 // error
-                wxLogSysError(_("Can not wait for thread termination"));
+                wxLogSysError(_("Cannot wait for thread termination"));
                 Kill();
                 return wxTHREAD_KILLED;
 
@@ -880,7 +905,8 @@ bool wxThreadInternal::Suspend()
     DWORD nSuspendCount = ::SuspendThread(m_hThread);
     if ( nSuspendCount == (DWORD)-1 )
     {
-        wxLogSysError(_("Can not suspend thread %x"), m_hThread);
+        wxLogSysError(_("Cannot suspend thread %lx"),
+                      static_cast<unsigned long>(wxPtrToUInt(m_hThread)));
 
         return false;
     }
@@ -895,7 +921,8 @@ bool wxThreadInternal::Resume()
     DWORD nSuspendCount = ::ResumeThread(m_hThread);
     if ( nSuspendCount == (DWORD)-1 )
     {
-        wxLogSysError(_("Can not resume thread %x"), m_hThread);
+        wxLogSysError(_("Cannot resume thread %lx"),
+                      static_cast<unsigned long>(wxPtrToUInt(m_hThread)));
 
         return false;
     }
@@ -1107,7 +1134,7 @@ wxThreadError wxThread::Resume()
 // stopping thread
 // ---------------
 
-wxThread::ExitCode wxThread::Wait()
+wxThread::ExitCode wxThread::Wait(wxThreadWait waitMode)
 {
     ExitCode rc = wxUIntToPtr(THREAD_ERROR_EXIT);
 
@@ -1116,14 +1143,14 @@ wxThread::ExitCode wxThread::Wait()
     wxCHECK_MSG( !IsDetached(), rc,
                  wxT("wxThread::Wait(): can't wait for detached thread") );
 
-    (void)m_internal->WaitForTerminate(m_critsect, &rc);
+    (void)m_internal->WaitForTerminate(m_critsect, &rc, waitMode);
 
     return rc;
 }
 
-wxThreadError wxThread::Delete(ExitCode *pRc)
+wxThreadError wxThread::Delete(ExitCode *pRc, wxThreadWait waitMode)
 {
-    return m_internal->WaitForTerminate(m_critsect, pRc, this);
+    return m_internal->WaitForTerminate(m_critsect, pRc, waitMode, this);
 }
 
 wxThreadError wxThread::Kill()
@@ -1149,6 +1176,8 @@ wxThreadError wxThread::Kill()
 
 void wxThread::Exit(ExitCode status)
 {
+    wxThreadInternal::DoThreadOnExit(this);
+
     m_internal->Free();
 
     if ( IsDetached() )
@@ -1261,7 +1290,7 @@ bool wxThreadModule::OnInit()
         ::TlsFree(gs_tlsThisThread);
         gs_tlsThisThread = 0xFFFFFFFF;
 
-        wxLogSysError(_("Thread module initialization failed: can not store value in thread local storage"));
+        wxLogSysError(_("Thread module initialization failed: cannot store value in thread local storage"));
 
         return false;
     }