From c112e10026f5ad27704c1447be81b51664a0e070 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Tue, 2 Apr 2002 15:37:57 +0000 Subject: [PATCH] changed wxCondition API to take a reference, not pointer, to wxMutex git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@14909 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- docs/latex/wx/conditn.tex | 7 +- include/wx/thread.h | 2 +- samples/console/console.cpp | 123 +++++++++++++++++++++++++++++++++--- src/msw/thread.cpp | 45 ++++--------- src/unix/threadpsx.cpp | 51 ++++++--------- 5 files changed, 152 insertions(+), 76 deletions(-) diff --git a/docs/latex/wx/conditn.tex b/docs/latex/wx/conditn.tex index bb71a7e7d7..44ba439509 100644 --- a/docs/latex/wx/conditn.tex +++ b/docs/latex/wx/conditn.tex @@ -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}} diff --git a/include/wx/thread.h b/include/wx/thread.h index ff78911271..60f5c7c5c4 100644 --- a/include/wx/thread.h +++ b/include/wx/thread.h @@ -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(); diff --git a/samples/console/console.cpp b/samples/console/console.cpp index f155e4b050..518f525f3c 100644 --- a/samples/console/console.cpp +++ b/samples/console/console.cpp @@ -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 diff --git a/src/msw/thread.cpp b/src/msw/thread.cpp index ec70911da4..7a42d2e60e 100644 --- a/src/msw/thread.cpp +++ b/src/msw/thread.cpp @@ -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; + wxMutex& m_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(); } // ---------------------------------------------------------------------------- diff --git a/src/unix/threadpsx.cpp b/src/unix/threadpsx.cpp index 48beb9ca6c..72be919335 100644 --- a/src/unix/threadpsx.cpp +++ b/src/unix/threadpsx.cpp @@ -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; + wxMutex& m_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; } -- 2.45.2