]> git.saurik.com Git - wxWidgets.git/blobdiff - src/unix/threadpsx.cpp
Applied [ 1613294 ] wxGetMouseState/wxIsKeyDown bug
[wxWidgets.git] / src / unix / threadpsx.cpp
index 1a9aaf6cfd0a12d644de79ff3e53a258e3159829..ff291daa3f114c0d07ba5ac9309edb167b03f6ae 100644 (file)
@@ -1,5 +1,5 @@
 /////////////////////////////////////////////////////////////////////////////
-// Name:        threadpsx.cpp
+// Name:        src/unix/threadpsx.cpp
 // Purpose:     wxThread (Posix) Implementation
 // Author:      Original from Wolfram Gloger/Guilhem Lavaux
 // Modified by: K. S. Sreeram (2002): POSIXified wxCondition, added wxSemaphore
 #if wxUSE_THREADS
 
 #include "wx/thread.h"
-#include "wx/module.h"
-#include "wx/utils.h"
-#include "wx/log.h"
-#include "wx/intl.h"
-#include "wx/dynarray.h"
-#include "wx/timer.h"
-#include "wx/stopwatch.h"
+
+#ifndef WX_PRECOMP
+    #include "wx/dynarray.h"
+    #include "wx/intl.h"
+    #include "wx/log.h"
+    #include "wx/utils.h"
+    #include "wx/timer.h"
+    #include "wx/stopwatch.h"
+    #include "wx/module.h"
+#endif
 
 #include <stdio.h>
 #include <unistd.h>
@@ -109,6 +112,9 @@ WX_DEFINE_ARRAY_PTR(wxThread *, wxArrayThread);
 // be left in memory
 static wxArrayThread gs_allThreads;
 
+// a mutex to protect gs_allThreads
+static wxMutex *gs_mutexAllThreads = NULL;
+
 // the id of the main thread
 static pthread_t gs_tidMain = (pthread_t)-1;
 
@@ -481,7 +487,7 @@ wxSemaphoreInternal::wxSemaphoreInternal(int initialcount, int maxcount)
     {
         wxFAIL_MSG( _T("wxSemaphore: invalid initial or maximal count") );
 
-        m_isOk = FALSE;
+        m_isOk = false;
     }
     else
     {
@@ -649,7 +655,7 @@ public:
     pthread_t GetId() const { return m_threadId; }
     pthread_t *GetIdPtr() { return &m_threadId; }
         // "cancelled" flag
-    void SetCancelFlag() { m_cancelled = TRUE; }
+    void SetCancelFlag() { m_cancelled = true; }
     bool WasCancelled() const { return m_cancelled; }
         // exit code
     void SetExitCode(wxThread::ExitCode exitcode) { m_exitcode = exitcode; }
@@ -664,8 +670,8 @@ public:
     {
         wxCriticalSectionLocker lock(m_csJoinFlag);
 
-        m_shouldBeJoined = FALSE;
-        m_isDetached = TRUE;
+        m_shouldBeJoined = false;
+        m_isDetached = true;
     }
 
 #ifdef wxHAVE_PTHREAD_CLEANUP
@@ -773,12 +779,21 @@ void *wxThreadInternal::PthreadStart(wxThread *thread)
         }
     }
 
-    // NB: at least under Linux, pthread_cleanup_push/pop are macros and pop
-    //     contains the matching '}' for the '{' in push, so they must be used
-    //     in the same block!
+    // NB: pthread_cleanup_push/pop() are macros and pop contains the matching
+    //     '}' for the '{' in push, so they must be used in the same block!
 #ifdef wxHAVE_PTHREAD_CLEANUP
+    #ifdef __DECCXX
+        // under Tru64 we get a warning from macro expansion
+        #pragma message save
+        #pragma message disable(declbutnotref)
+    #endif
+
     // remove the cleanup handler without executing it
     pthread_cleanup_pop(FALSE);
+
+    #ifdef __DECCXX
+        #pragma message restore
+    #endif
 #endif // wxHAVE_PTHREAD_CLEANUP
 
     if ( dontRunAtAll )
@@ -809,6 +824,7 @@ extern "C" void wxPthreadCleanup(void *ptr)
 
 void wxThreadInternal::Cleanup(wxThread *thread)
 {
+    if (pthread_getspecific(gs_keySelf) == 0) return;
     {
         wxCriticalSectionLocker lock(thread->m_critsect);
         if ( thread->m_internal->GetState() == STATE_EXITED )
@@ -831,17 +847,17 @@ void wxThreadInternal::Cleanup(wxThread *thread)
 wxThreadInternal::wxThreadInternal()
 {
     m_state = STATE_NEW;
-    m_cancelled = FALSE;
+    m_cancelled = false;
     m_prio = WXTHREAD_DEFAULT_PRIORITY;
     m_threadId = 0;
     m_exitcode = 0;
 
-    // set to TRUE only when the thread starts waiting on m_semSuspend
-    m_isPaused = FALSE;
+    // set to true only when the thread starts waiting on m_semSuspend
+    m_isPaused = false;
 
     // defaults for joinable threads
-    m_shouldBeJoined = TRUE;
-    m_isDetached = FALSE;
+    m_shouldBeJoined = true;
+    m_isDetached = false;
 }
 
 wxThreadInternal::~wxThreadInternal()
@@ -894,7 +910,7 @@ void wxThreadInternal::Wait()
                 wxLogError(_("Failed to join a thread, potential memory leak detected - please restart the program"));
             }
 
-            m_shouldBeJoined = FALSE;
+            m_shouldBeJoined = false;
         }
     }
 
@@ -933,7 +949,7 @@ void wxThreadInternal::Resume()
         m_semSuspend.Post();
 
         // reset the flag
-        SetReallyPaused(FALSE);
+        SetReallyPaused(false);
     }
     else
     {
@@ -1052,7 +1068,11 @@ bool wxThread::SetConcurrency(size_t level)
 wxThread::wxThread(wxThreadKind kind)
 {
     // add this thread to the global list of all threads
-    gs_allThreads.Add(this);
+    {
+        wxMutexLocker lock(*gs_mutexAllThreads);
+
+        gs_allThreads.Add(this);
+    }
 
     m_internal = new wxThreadInternal();
 
@@ -1411,13 +1431,14 @@ wxThreadError wxThread::Kill()
         default:
 #ifdef HAVE_PTHREAD_CANCEL
             if ( pthread_cancel(m_internal->GetId()) != 0 )
-#endif
+#endif // HAVE_PTHREAD_CANCEL
             {
                 wxLogError(_("Failed to terminate a thread."));
 
                 return wxTHREAD_MISC_ERROR;
             }
 
+#ifdef HAVE_PTHREAD_CANCEL
             if ( m_isDetached )
             {
                 // if we use cleanup function, this will be done from
@@ -1437,6 +1458,7 @@ wxThreadError wxThread::Kill()
             }
 
             return wxTHREAD_NO_ERROR;
+#endif // HAVE_PTHREAD_CANCEL
     }
 }
 
@@ -1470,6 +1492,7 @@ void wxThread::Exit(ExitCode status)
         //       we make it a global object, but this would mean that we can
         //       only call one thread function at a time :-(
         DeleteThread(this);
+        pthread_setspecific(gs_keySelf, 0);
     }
     else
     {
@@ -1494,7 +1517,7 @@ bool wxThread::TestDestroy()
 
     if ( m_internal->GetState() == STATE_PAUSED )
     {
-        m_internal->SetReallyPaused(TRUE);
+        m_internal->SetReallyPaused(true);
 
         // leave the crit section or the other threads will stop too if they
         // try to call any of (seemingly harmless) IsXXX() functions while we
@@ -1531,7 +1554,11 @@ wxThread::~wxThread()
     delete m_internal;
 
     // remove this thread from the global array
-    gs_allThreads.Remove(this);
+    {
+        wxMutexLocker lock(*gs_mutexAllThreads);
+
+        gs_allThreads.Remove(this);
+    }
 }
 
 // -----------------------------------------------------------------------------
@@ -1553,10 +1580,10 @@ bool wxThread::IsAlive() const
     {
         case STATE_RUNNING:
         case STATE_PAUSED:
-            return TRUE;
+            return true;
 
         default:
-            return FALSE;
+            return false;
     }
 }
 
@@ -1590,18 +1617,20 @@ bool wxThreadModule::OnInit()
     {
         wxLogSysError(rc, _("Thread module initialization failed: failed to create thread key"));
 
-        return FALSE;
+        return false;
     }
 
     gs_tidMain = pthread_self();
 
+    gs_mutexAllThreads = new wxMutex();
+
     gs_mutexGui = new wxMutex();
     gs_mutexGui->Lock();
 
     gs_mutexDeleteThread = new wxMutex();
-    gs_condAllDeleted = new wxCondition( *gs_mutexDeleteThread );
+    gs_condAllDeleted = new wxCondition(*gs_mutexDeleteThread);
 
-    return TRUE;
+    return true;
 }
 
 void wxThreadModule::OnExit()
@@ -1626,13 +1655,19 @@ void wxThreadModule::OnExit()
         }
     }
 
-    // terminate any threads left
-    size_t count = gs_allThreads.GetCount();
-    if ( count != 0u )
+    size_t count;
+
     {
-        wxLogDebug(wxT("%lu threads were not terminated by the application."),
-                   (unsigned long)count);
-    }
+        wxMutexLocker lock(*gs_mutexAllThreads);
+
+        // terminate any threads left
+        count = gs_allThreads.GetCount();
+        if ( count != 0u )
+        {
+            wxLogDebug(wxT("%lu threads were not terminated by the application."),
+                       (unsigned long)count);
+        }
+    } // unlock mutex before deleting the threads as they lock it in their dtor
 
     for ( size_t n = 0u; n < count; n++ )
     {
@@ -1641,6 +1676,8 @@ void wxThreadModule::OnExit()
         gs_allThreads[0]->Delete();
     }
 
+    delete gs_mutexAllThreads;
+
     // destroy GUI mutex
     gs_mutexGui->Unlock();
     delete gs_mutexGui;
@@ -1664,7 +1701,7 @@ static void ScheduleThreadForDeletion()
 
     wxLogTrace(TRACE_THREADS, _T("%lu thread%s waiting to be deleted"),
                (unsigned long)gs_nThreadsBeingDeleted,
-               gs_nThreadsBeingDeleted == 1 ? "" : "s");
+               gs_nThreadsBeingDeleted == 1 ? _T("") : _T("s"));
 }
 
 static void DeleteThread(wxThread *This)
@@ -1707,4 +1744,3 @@ void wxMutexGuiLeave()
 #include "wx/thrimpl.cpp"
 
 #endif // wxUSE_THREADS
-