changed wxCondition API to take a reference, not pointer, to wxMutex
authorVadim Zeitlin <vadim@wxwidgets.org>
Tue, 2 Apr 2002 15:37:57 +0000 (15:37 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Tue, 2 Apr 2002 15:37:57 +0000 (15:37 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14909 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

docs/latex/wx/conditn.tex
include/wx/thread.h
samples/console/console.cpp
src/msw/thread.cpp
src/unix/threadpsx.cpp

index bb71a7e7d70671685ed1760b45d0319f7ea952ed..44ba4395096cba093bed5a68f6f8afc1a2e9d351 100644 (file)
@@ -53,7 +53,7 @@ private:
 int main()
 {
     wxMutex mutex;
-    wxCondition condition(&mutex);
+    wxCondition condition(mutex);
 
     for ( int i = 0; i < 10; i++ )
     {
@@ -90,9 +90,10 @@ None.
 
 \membersection{wxCondition::wxCondition}\label{wxconditionconstr}
 
-\func{}{wxCondition}{\param{wxMutex }{*mutex}}
+\func{}{wxCondition}{\param{wxMutex\& }{mutex}}
 
-Default and only constructor. The {\it mutex} must be non {\tt NULL}.
+Default and only constructor. The {\it mutex} must be locked by the caller
+before calling \helpref{Wait}{wxconditionwait} function.
 
 \membersection{wxCondition::\destruct{wxCondition}}
 
index ff789112718ea35c026265a30bd6ea9a5f561108..60f5c7c5c44b7f4fdf2c71252a438817fb4b2442 100644 (file)
@@ -225,7 +225,7 @@ public:
 
     // Each wxCondition object is associated with with a wxMutex object The
     // mutex object MUST be locked before calling Wait()
-    wxCondition( wxMutex *mutex );
+    wxCondition(wxMutex& mutex);
 
     // dtor is not virtual, don't use this class polymorphically
     ~wxCondition();
index f155e4b05094370a19b2a62eef53733106ee2b8b..518f525f3caff419b98e43b43811124fc1d6c2c3 100644 (file)
@@ -91,7 +91,7 @@
     #undef TEST_ALL
     static const bool TEST_ALL = TRUE;
 #else
-    #define TEST_FILENAME
+    #define TEST_THREADS
 
     static const bool TEST_ALL = FALSE;
 #endif
@@ -4627,7 +4627,7 @@ static void TestTimeCompatibility()
 
 static size_t gs_counter = (size_t)-1;
 static wxCriticalSection gs_critsect;
-static wxCondition gs_cond;
+static wxSemaphore gs_cond;
 
 class MyJoinableThread : public wxThread
 {
@@ -4715,7 +4715,7 @@ void MyDetachedThread::OnExit()
 
     wxCriticalSectionLocker lock(gs_critsect);
     if ( !--gs_counter && !m_cancelled )
-        gs_cond.Signal();
+        gs_cond.Post();
 }
 
 static void TestDetachedThreads()
@@ -4854,8 +4854,9 @@ static void TestThreadDelete()
 class MyWaitingThread : public wxThread
 {
 public:
-    MyWaitingThread(wxCondition *condition)
+    MyWaitingThread( wxMutex *mutex, wxCondition *condition )
     {
+        m_mutex = mutex;
         m_condition = condition;
 
         Create();
@@ -4866,12 +4867,14 @@ public:
         printf("Thread %lu has started running.\n", GetId());
         fflush(stdout);
 
-        gs_cond.Signal();
+        gs_cond.Post();
 
         printf("Thread %lu starts to wait...\n", GetId());
         fflush(stdout);
 
+        m_mutex->Lock();
         m_condition->Wait();
+        m_mutex->Unlock();
 
         printf("Thread %lu finished to wait, exiting.\n", GetId());
         fflush(stdout);
@@ -4880,17 +4883,19 @@ public:
     }
 
 private:
+    wxMutex *m_mutex;
     wxCondition *m_condition;
 };
 
 static void TestThreadConditions()
 {
-    wxCondition condition;
+    wxMutex mutex;
+    wxCondition condition(mutex);
 
     // otherwise its difficult to understand which log messages pertain to
     // which condition
-    wxLogTrace("thread", "Local condition var is %08x, gs_cond = %08x",
-               condition.GetId(), gs_cond.GetId());
+    //wxLogTrace("thread", "Local condition var is %08x, gs_cond = %08x",
+    //           condition.GetId(), gs_cond.GetId());
 
     // create and launch threads
     MyWaitingThread *threads[10];
@@ -4898,7 +4903,7 @@ static void TestThreadConditions()
     size_t n;
     for ( n = 0; n < WXSIZEOF(threads); n++ )
     {
-        threads[n] = new MyWaitingThread(&condition);
+        threads[n] = new MyWaitingThread( &mutex, &condition );
     }
 
     for ( n = 0; n < WXSIZEOF(threads); n++ )
@@ -4944,6 +4949,102 @@ static void TestThreadConditions()
     wxThread::Sleep(500);
 }
 
+#include "wx/utils.h"
+
+class MyExecThread : public wxThread
+{
+public:
+    MyExecThread(const wxString& command) : wxThread(wxTHREAD_JOINABLE),
+                                            m_command(command)
+    {
+        Create();
+    }
+
+    virtual ExitCode Entry()
+    {
+        return (ExitCode)wxExecute(m_command, wxEXEC_SYNC);
+    }
+
+private:
+    wxString m_command;
+};
+
+static void TestThreadExec()
+{
+    wxPuts(_T("*** Testing wxExecute interaction with threads ***\n"));
+
+    MyExecThread thread(_T("true"));
+    thread.Run();
+
+    wxPrintf(_T("Main program exit code: %ld.\n"),
+             wxExecute(_T("false"), wxEXEC_SYNC));
+
+    wxPrintf(_T("Thread exit code: %ld.\n"), (long)thread.Wait());
+}
+
+// semaphore tests
+#include "wx/datetime.h"
+
+class MySemaphoreThread : public wxThread
+{
+public:
+    MySemaphoreThread(int i, wxSemaphore *sem)
+        : wxThread(wxTHREAD_JOINABLE),
+          m_sem(sem),
+          m_i(i)
+    {
+        Create();
+    }
+
+    virtual ExitCode Entry()
+    {
+        wxPrintf(_T("%s: Thread %d starting to wait for semaphore...\n"),
+                 wxDateTime::Now().FormatTime().c_str(), m_i);
+
+        m_sem->Wait();
+
+        wxPrintf(_T("%s: Thread %d acquired the semaphore.\n"),
+                 wxDateTime::Now().FormatTime().c_str(), m_i);
+
+        Sleep(1000);
+
+        wxPrintf(_T("%s: Thread %d releasing the semaphore.\n"),
+                 wxDateTime::Now().FormatTime().c_str(), m_i);
+
+        m_sem->Post();
+
+        return 0;
+    }
+
+private:
+    wxSemaphore *m_sem;
+    int m_i;
+};
+
+WX_DEFINE_ARRAY(wxThread *, ArrayThreads);
+
+static void TestSemaphore()
+{
+    wxPuts(_T("*** Testing wxSemaphore class. ***"));
+
+    static const int SEM_LIMIT = 3;
+
+    wxSemaphore sem(SEM_LIMIT, SEM_LIMIT);
+    ArrayThreads threads;
+
+    for ( int i = 0; i < 3*SEM_LIMIT; i++ )
+    {
+        threads.Add(new MySemaphoreThread(i, &sem));
+        threads.Last()->Run();
+    }
+
+    for ( size_t n = 0; n < threads.GetCount(); n++ )
+    {
+        threads[n]->Wait();
+        delete threads[n];
+    }
+}
+
 #endif // TEST_THREADS
 
 // ----------------------------------------------------------------------------
@@ -5851,9 +5952,11 @@ int main(int argc, char **argv)
         TestJoinableThreads();
         TestThreadSuspend();
         TestThreadDelete();
+        TestThreadConditions();
+        TestThreadExec();
     }
 
-    TestThreadConditions();
+    TestSemaphore();
 #endif // TEST_THREADS
 
 #ifdef TEST_TIMER
index ec70911da4b7417af88215ff9c3a05923646b1c2..7a42d2e60e0fceddac1372020a5fef241877f7ad 100644 (file)
@@ -354,8 +354,7 @@ void wxSemaphore::Post()
 class wxConditionInternal
 {
 public:
-    wxConditionInternal( wxMutex *mutex );
-    ~wxConditionInternal();
+    wxConditionInternal(wxMutex& mutex);
 
     void Wait();
 
@@ -369,22 +368,18 @@ private:
     int m_numWaiters;
     wxMutex m_mutexNumWaiters;
 
-    wxMutex *m_mutex;
+    wxMutexm_mutex;
 
     wxSemaphore m_semaphore;
 };
 
-wxConditionInternal::wxConditionInternal( wxMutex *mutex )
+wxConditionInternal::wxConditionInternal(wxMutex& mutex)
+                   : m_mutex(mutex)
 {
-    m_mutex = mutex;
 
     m_numWaiters = 0;
 }
 
-wxConditionInternal::~wxConditionInternal()
-{
-}
-
 void wxConditionInternal::Wait()
 {
     // increment the number of waiters
@@ -392,7 +387,7 @@ void wxConditionInternal::Wait()
     m_numWaiters++;
     m_mutexNumWaiters.Unlock();
 
-    m_mutex->Unlock();
+    m_mutex.Unlock();
 
     // a potential race condition can occur here
     //
@@ -407,7 +402,7 @@ void wxConditionInternal::Wait()
     // wait ( if necessary ) and decrement semaphore
     m_semaphore.Wait();
 
-    m_mutex->Lock();
+    m_mutex.Lock();
 }
 
 bool wxConditionInternal::Wait( unsigned long timeout_millis )
@@ -416,7 +411,7 @@ bool wxConditionInternal::Wait( unsigned long timeout_millis )
     m_numWaiters++;
     m_mutexNumWaiters.Unlock();
 
-    m_mutex->Unlock();
+    m_mutex.Unlock();
 
     // a race condition can occur at this point in the code
     //
@@ -452,7 +447,7 @@ bool wxConditionInternal::Wait( unsigned long timeout_millis )
         m_mutexNumWaiters.Unlock();
     }
 
-    m_mutex->Lock();
+    m_mutex.Lock();
 
     return success;
 }
@@ -489,18 +484,9 @@ void wxConditionInternal::Broadcast()
 // wxCondition implementation
 // ----------------------------------------------------------------------------
 
-wxCondition::wxCondition( wxMutex *mutex )
+wxCondition::wxCondition(wxMutex& mutex)
 {
-    if ( !mutex )
-    {
-        wxFAIL_MSG( _T("NULL mutex in wxCondition ctor") );
-
-        m_internal = NULL;
-    }
-    else
-    {
-        m_internal = new wxConditionInternal( mutex );
-    }
+    m_internal = new wxConditionInternal( mutex );
 }
 
 wxCondition::~wxCondition()
@@ -510,25 +496,22 @@ wxCondition::~wxCondition()
 
 void wxCondition::Wait()
 {
-    if ( m_internal )
-        m_internal->Wait();
+    m_internal->Wait();
 }
 
 bool wxCondition::Wait( unsigned long timeout_millis )
 {
-    return m_internal ? m_internal->Wait(timeout_millis) : FALSE;
+    return m_internal->Wait(timeout_millis);
 }
 
 void wxCondition::Signal()
 {
-    if ( m_internal )
-        m_internal->Signal();
+    m_internal->Signal();
 }
 
 void wxCondition::Broadcast()
 {
-    if ( m_internal )
-        m_internal->Broadcast();
+    m_internal->Broadcast();
 }
 
 // ----------------------------------------------------------------------------
index 48beb9ca6cff5e0fec4d81868e327ba4b5adb955..72be9193352b2b1191d936e2f62c4e449b37b131 100644 (file)
@@ -319,7 +319,7 @@ wxMutexError wxMutex::Unlock()
 class wxConditionInternal
 {
 public:
-    wxConditionInternal( wxMutex *mutex );
+    wxConditionInternal(wxMutex& mutex);
     ~wxConditionInternal();
 
     void Wait();
@@ -331,14 +331,16 @@ public:
     void Broadcast();
 
 private:
+    // get the POSIX mutex associated with us
+    pthread_mutex_t *GetMutex() const { return &m_mutex.m_internal->m_mutex; }
 
-    wxMutex *m_mutex;
+    wxMutexm_mutex;
     pthread_cond_t m_cond;
 };
 
-wxConditionInternal::wxConditionInternal( wxMutex *mutex )
+wxConditionInternal::wxConditionInternal(wxMutex& mutex)
+                   : m_mutex(mutex)
 {
-    m_mutex = mutex;
     if ( pthread_cond_init( &m_cond, NULL ) != 0 )
     {
         wxLogDebug(_T("pthread_cond_init() failed"));
@@ -355,7 +357,7 @@ wxConditionInternal::~wxConditionInternal()
 
 void wxConditionInternal::Wait()
 {
-    if ( pthread_cond_wait( &m_cond, &(m_mutex->m_internal->m_mutex) ) != 0 )
+    if ( pthread_cond_wait( &m_cond, GetMutex() ) != 0 )
     {
         wxLogDebug(_T("pthread_cond_wait() failed"));
     }
@@ -363,13 +365,14 @@ void wxConditionInternal::Wait()
 
 bool wxConditionInternal::Wait( const timespec *ts )
 {
-    int result = pthread_cond_timedwait( &m_cond,
-                                         &(m_mutex->m_internal->m_mutex),
-                                         ts );
+    int result = pthread_cond_timedwait( &m_cond, GetMutex(), ts );
     if ( result == ETIMEDOUT )
         return FALSE;
 
-    wxASSERT_MSG( result == 0, _T("pthread_cond_timedwait() failed") );
+    if ( result != 0 )
+    {
+        wxLogDebug(_T("pthread_cond_timedwait() failed"));
+    }
 
     return TRUE;
 }
@@ -397,18 +400,9 @@ void wxConditionInternal::Broadcast()
 // wxCondition
 // ---------------------------------------------------------------------------
 
-wxCondition::wxCondition( wxMutex *mutex )
+wxCondition::wxCondition(wxMutex& mutex)
 {
-    if ( !mutex )
-    {
-        wxFAIL_MSG( _T("NULL mutex in wxCondition ctor") );
-
-        m_internal = NULL;
-    }
-    else
-    {
-        m_internal = new wxConditionInternal( mutex );
-    }
+    m_internal = new wxConditionInternal( mutex );
 }
 
 wxCondition::~wxCondition()
@@ -418,14 +412,11 @@ wxCondition::~wxCondition()
 
 void wxCondition::Wait()
 {
-    if ( m_internal )
-        m_internal->Wait();
+    m_internal->Wait();
 }
 
 bool wxCondition::Wait( unsigned long timeout_millis )
 {
-    wxCHECK_MSG( m_internal, FALSE, _T("can't wait on uninitalized condition") );
-
     wxLongLong curtime = wxGetLocalTimeMillis();
     curtime += timeout_millis;
     wxLongLong temp = curtime / 1000;
@@ -444,14 +435,12 @@ bool wxCondition::Wait( unsigned long timeout_millis )
 
 void wxCondition::Signal()
 {
-    if ( m_internal )
-        m_internal->Signal();
+    m_internal->Signal();
 }
 
 void wxCondition::Broadcast()
 {
-    if ( m_internal )
-        m_internal->Broadcast();
+    m_internal->Broadcast();
 }
 
 // ===========================================================================
@@ -483,7 +472,7 @@ private:
 };
 
 wxSemaphoreInternal::wxSemaphoreInternal( int initialcount, int maxcount )
-                   : m_cond(&m_mutex)
+                   : m_cond(m_mutex)
 {
 
     if ( (initialcount < 0) || ((maxcount > 0) && (initialcount > maxcount)) )
@@ -602,7 +591,7 @@ public:
         m_signaled = FALSE;
 
         m_mutex = new wxMutex();
-        m_cond = new wxCondition( m_mutex );
+        m_cond = new wxCondition( *m_mutex );
     }
 
     // increment the reference count
@@ -1711,7 +1700,7 @@ bool wxThreadModule::OnInit()
 #endif // wxUSE_GUI
 
     gs_mutexDeleteThread = new wxMutex();
-    gs_condAllDeleted = new wxCondition( gs_mutexDeleteThread );
+    gs_condAllDeleted = new wxCondition( *gs_mutexDeleteThread );
 
     return TRUE;
 }