]> git.saurik.com Git - wxWidgets.git/commitdiff
attempts to make wxCondition::Broadcast() work - it still doesn't
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 29 Jan 2002 22:49:13 +0000 (22:49 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 29 Jan 2002 22:49:13 +0000 (22:49 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@13919 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

include/wx/thread.h
src/unix/threadpsx.cpp

index 72c708e51ffef4f5b3e693a5908ba13547fd0d46..1b7717fc6cfa2c080c8b435f87c2ce9e88a53574 100644 (file)
@@ -234,7 +234,7 @@ public:
     // signal the condition
         // wakes up one (and only one) of the waiting threads
     void Signal();
-        // wakes up all threads waiting onthis condition
+        // wakes up all threads waiting on this condition
     void Broadcast();
 
 private:
@@ -254,6 +254,13 @@ private:
 //     created by the wxThread object while "main thread" is the thread created
 //     during the process initialization (a.k.a. the GUI thread)
 
+// On VMS thread pointers are 64 bits (also needed for other systems???
+#ifdef __VMS
+   typedef unsigned long long wxThreadIdType;
+#else
+   typedef unsigned long wxThreadIdType;
+#endif
+
 class wxThreadInternal;
 class WXDLLEXPORT wxThread
 {
@@ -289,13 +296,8 @@ public:
         // Get the platform specific thread ID and return as a long.  This
         // can be used to uniquely identify threads, even if they are not
         // wxThreads.  This is used by wxPython.
-       // On VMS thread pointers are 64 bits (also needed for other systems???
-#ifdef __VMS
-   static unsigned long long GetCurrentId();
-#else
-   static unsigned long GetCurrentId();
-#endif
-   
+   static wxThreadIdType GetCurrentId();
+
         // sets the concurrency level: this is, roughly, the number of threads
         // the system tries to schedule to run in parallel. 0 means the
         // default value (usually acceptable, but may not yield the best
@@ -381,11 +383,7 @@ public:
 
     // Get the thread ID - a platform dependent number which uniquely
     // identifies a thread inside a process
-#ifdef __VMS
-   unsigned long long GetId() const;
-#else
-   unsigned long GetId() const;
-#endif
+    wxThreadIdType GetId() const;
 
     // called when the thread exits - in the context of this thread
     //
index e10fe97e82d98353f1d127f6e71afc17424e06d8..7054897738486c2fbad7f3b6fd59ab468bdc5e4c 100644 (file)
 #include "wx/log.h"
 #include "wx/intl.h"
 #include "wx/dynarray.h"
+#include "wx/listimpl.cpp"
 
 #include <stdio.h>
 #include <unistd.h>
 #include <pthread.h>
 #include <errno.h>
 #include <time.h>
-
 #if HAVE_SCHED_H
     #include <sched.h>
 #endif
@@ -257,6 +257,8 @@ wxMutexError wxMutex::Unlock()
 // remember that the condition was signaled and to return from Wait()
 // immediately in this case (this is more like Win32 automatic event objects)
 
+WX_DECLARE_LIST(pthread_mutex_t, wxMutexList);
+
 class wxConditionInternal
 {
 public:
@@ -269,25 +271,32 @@ public:
     void Signal();
     void Broadcast();
 
-    void WaitDone();
-    bool ShouldWait();
+    void WaitDone(wxMutexList::Node *mutexnode);
+    wxMutexList::Node *ShouldWait();
     bool HasWaiters();
 
 private:
-    bool m_wasSignaled;             // TRUE if condition was signaled while
-                                    // nobody waited for it
-    size_t m_nWaiters;              // TRUE if someone already waits for us
+    void LockAllMutexes();          // locks all mutexes on the list
+    void UnlockAllMutexes();       // unlocks mutexes after signaling / broadcasting
+
+    // TRUE if condition was signaled while nobody waited for it
+    bool m_wasSignaled;
+
+    // protects access to vars above
+    pthread_mutex_t m_mutexProtect;
 
-    pthread_mutex_t m_mutexProtect; // protects access to vars above
+    // the mutexes which are used for the condition variable
+    wxMutexList m_mutexes;
 
-    pthread_mutex_t m_mutex;        // the mutex used with the condition
-    pthread_cond_t m_condition;     // the condition itself
+    // the condition itself
+    pthread_cond_t m_condition;
 };
 
+WX_DEFINE_LIST(wxMutexList);
+
 wxConditionInternal::wxConditionInternal()
 {
     m_wasSignaled = FALSE;
-    m_nWaiters = 0;
 
     if ( pthread_cond_init(&m_condition, (pthread_condattr_t *)NULL) != 0 )
     {
@@ -295,19 +304,12 @@ wxConditionInternal::wxConditionInternal()
         wxFAIL_MSG( _T("pthread_cond_init() failed") );
     }
 
-    if ( pthread_mutex_init(&m_mutex, (pthread_mutexattr_t *)NULL) != 0 ||
-         pthread_mutex_init(&m_mutexProtect, NULL) != 0 )
+    if ( pthread_mutex_init(&m_mutexProtect, NULL) != 0 )
     {
         // neither this
         wxFAIL_MSG( _T("wxCondition: pthread_mutex_init() failed") );
     }
 
-    // initially the mutex is locked, so no thread can Signal() or Broadcast()
-    // until another thread starts to Wait()
-    if ( pthread_mutex_lock(&m_mutex) != 0 )
-    {
-        wxFAIL_MSG( _T("wxCondition: pthread_mutex_lock() failed") );
-    }
 }
 
 wxConditionInternal::~wxConditionInternal()
@@ -318,27 +320,40 @@ wxConditionInternal::~wxConditionInternal()
                       "threads are probably still waiting on it?)"));
     }
 
-    if ( pthread_mutex_unlock( &m_mutex ) != 0 )
+    for ( wxMutexList::Node *node = m_mutexes.GetFirst();
+          node;
+          node = node->GetNext() )
     {
-        wxLogDebug(_T("wxCondition: failed to unlock the mutex"));
+        pthread_mutex_t *currentmutex = node->GetData();
+        if ( pthread_mutex_unlock( currentmutex ) != 0 )
+        {
+            wxLogDebug(_T("wxCondition: failed to unlock the mutex"));
+        } else {
+            delete currentmutex;
+        }
     }
 
-    if ( pthread_mutex_destroy( &m_mutex ) != 0 ||
-         pthread_mutex_destroy( &m_mutexProtect ) != 0 )
+    m_mutexes.DeleteContents(TRUE);
+
+    if ( pthread_mutex_destroy( &m_mutexProtect ) != 0 )
     {
         wxLogDebug(_T("Failed to destroy mutex (it is probably locked)"));
     }
 }
 
-void wxConditionInternal::WaitDone()
+void wxConditionInternal::WaitDone(wxMutexList::Node *mutexnode)
 {
     MutexLock lock(m_mutexProtect);
 
-    m_wasSignaled = FALSE;
-    m_nWaiters--;
+    pthread_mutex_unlock(mutexnode->GetData());
+    pthread_mutex_destroy(mutexnode->GetData());
+    delete mutexnode->GetData();
+
+    m_mutexes.DeleteNode(mutexnode);
+
 }
 
-bool wxConditionInternal::ShouldWait()
+wxMutexList::Node *wxConditionInternal::ShouldWait()
 {
     MutexLock lock(m_mutexProtect);
 
@@ -348,20 +363,26 @@ bool wxConditionInternal::ShouldWait()
         // flag and return
         m_wasSignaled = FALSE;
 
-        return FALSE;
+        return NULL;
     }
 
     // we start to wait for it
-    m_nWaiters++;
 
-    return TRUE;
+    pthread_mutex_t *waitmutex = new pthread_mutex_t;
+    if ( pthread_mutex_init(waitmutex, (pthread_mutexattr_t *)NULL) != 0 )
+    {
+        // neither this
+        wxFAIL_MSG( _T("wxCondition: pthread_mutex_init() failed when starting waiting") );
+    }
+
+    pthread_mutex_lock(waitmutex);
+
+    return ( m_mutexes.Append(waitmutex) );
 }
 
 bool wxConditionInternal::HasWaiters()
 {
-    MutexLock lock(m_mutexProtect);
-
-    if ( m_nWaiters )
+    if ( m_mutexes.GetCount() )
     {
         // someone waits for us, signal the condition normally
         return TRUE;
@@ -376,25 +397,29 @@ bool wxConditionInternal::HasWaiters()
 
 void wxConditionInternal::Wait()
 {
-    if ( ShouldWait() )
+    wxMutexList::Node *ownmutexnode = ShouldWait();
+
+    if ( ownmutexnode )
     {
-        if ( pthread_cond_wait( &m_condition, &m_mutex ) != 0 )
+        if ( pthread_cond_wait( &m_condition, ownmutexnode->GetData() ) != 0 )
         {
             // not supposed to ever happen
             wxFAIL_MSG( _T("pthread_cond_wait() failed") );
         }
-    }
 
-    WaitDone();
+        WaitDone(ownmutexnode);
+    }
 }
 
 bool wxConditionInternal::WaitWithTimeout(const timespec* ts)
 {
     bool ok;
 
-    if ( ShouldWait() )
+    wxMutexList::Node *ownmutexnode = ShouldWait();
+
+    if ( ownmutexnode )
     {
-        switch ( pthread_cond_timedwait( &m_condition, &m_mutex, ts ) )
+        switch ( pthread_cond_timedwait( &m_condition, ownmutexnode->GetData(), ts ) )
         {
             case 0:
                 // condition signaled
@@ -411,6 +436,7 @@ bool wxConditionInternal::WaitWithTimeout(const timespec* ts)
                 // wait interrupted or timeout elapsed
                 ok = FALSE;
         }
+        WaitDone(ownmutexnode);
     }
     else
     {
@@ -418,36 +444,65 @@ bool wxConditionInternal::WaitWithTimeout(const timespec* ts)
         ok = TRUE;
     }
 
-    WaitDone();
 
     return ok;
 }
 
+void wxConditionInternal::LockAllMutexes()
+{
+    wxMutexList::Node *mutexnode = m_mutexes.GetFirst();
+    while ( mutexnode )
+    {
+        pthread_mutex_lock(mutexnode->GetData());
+        mutexnode = mutexnode->GetNext();
+    }
+}
+
+void wxConditionInternal::UnlockAllMutexes()
+{
+    wxMutexList::Node *mutexnode = m_mutexes.GetFirst();
+    while ( mutexnode )
+    {
+        pthread_mutex_unlock(mutexnode->GetData());
+        mutexnode = mutexnode->GetNext();
+    }
+}
+
 void wxConditionInternal::Signal()
 {
+    // calls to HasWaiters() must be serialized
+    MutexLock lock(m_mutexProtect);
+
     if ( HasWaiters() )
     {
-        MutexLock lock(m_mutex);
+        // wait 
+        LockAllMutexes();
 
         if ( pthread_cond_signal( &m_condition ) != 0 )
         {
             // shouldn't ever happen
             wxFAIL_MSG(_T("pthread_cond_signal() failed"));
         }
+
+        UnlockAllMutexes();
     }
 }
 
 void wxConditionInternal::Broadcast()
 {
+    MutexLock lock(m_mutexProtect);
+
     if ( HasWaiters() )
     {
-        MutexLock lock(m_mutex);
+        LockAllMutexes();
 
         if ( pthread_cond_broadcast( &m_condition ) != 0 )
         {
             // shouldn't ever happen
             wxFAIL_MSG(_T("pthread_cond_broadcast() failed"));
         }
+
+        UnlockAllMutexes();
     }
 }
 
@@ -763,13 +818,10 @@ void wxThreadInternal::Wait()
         wxMutexGuiLeave();
 
     bool isDetached = m_isDetached;
-#ifdef __VMS
-   long long id = (long long)GetId();
-#else
-   long id = (long)GetId();
-#endif
-   wxLogTrace(TRACE_THREADS, _T("Starting to wait for thread %ld to exit."),
-               id);
+    wxThreadIdType id = GetId();
+
+    wxLogTrace(TRACE_THREADS,
+               _T("Starting to wait for thread %ld to exit."), id);
 
     // wait until the thread terminates (we're blocking in _another_ thread,
     // of course)
@@ -1142,15 +1194,9 @@ unsigned int wxThread::GetPriority() const
     return m_internal->GetPriority();
 }
 
-#ifdef __VMS
-unsigned long long wxThread::GetId() const
+wxThreadIdType wxThread::GetId() const
 {
-    return (unsigned long long)m_internal->GetId();
-#else
-unsigned long wxThread::GetId() const
-{
-    return (unsigned long)m_internal->GetId();
-#endif
+    return m_internal->GetId();
 }
 
 // -----------------------------------------------------------------------------