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
This commit is contained in:
Vadim Zeitlin
2002-04-02 15:37:57 +00:00
parent cd10339a23
commit c112e10026
5 changed files with 152 additions and 76 deletions

View File

@@ -53,7 +53,7 @@ private:
int main() int main()
{ {
wxMutex mutex; wxMutex mutex;
wxCondition condition(&mutex); wxCondition condition(mutex);
for ( int i = 0; i < 10; i++ ) for ( int i = 0; i < 10; i++ )
{ {
@@ -90,9 +90,10 @@ None.
\membersection{wxCondition::wxCondition}\label{wxconditionconstr} \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}} \membersection{wxCondition::\destruct{wxCondition}}

View File

@@ -225,7 +225,7 @@ public:
// Each wxCondition object is associated with with a wxMutex object The // Each wxCondition object is associated with with a wxMutex object The
// mutex object MUST be locked before calling Wait() // mutex object MUST be locked before calling Wait()
wxCondition( wxMutex *mutex ); wxCondition(wxMutex& mutex);
// dtor is not virtual, don't use this class polymorphically // dtor is not virtual, don't use this class polymorphically
~wxCondition(); ~wxCondition();

View File

@@ -91,7 +91,7 @@
#undef TEST_ALL #undef TEST_ALL
static const bool TEST_ALL = TRUE; static const bool TEST_ALL = TRUE;
#else #else
#define TEST_FILENAME #define TEST_THREADS
static const bool TEST_ALL = FALSE; static const bool TEST_ALL = FALSE;
#endif #endif
@@ -4627,7 +4627,7 @@ static void TestTimeCompatibility()
static size_t gs_counter = (size_t)-1; static size_t gs_counter = (size_t)-1;
static wxCriticalSection gs_critsect; static wxCriticalSection gs_critsect;
static wxCondition gs_cond; static wxSemaphore gs_cond;
class MyJoinableThread : public wxThread class MyJoinableThread : public wxThread
{ {
@@ -4715,7 +4715,7 @@ void MyDetachedThread::OnExit()
wxCriticalSectionLocker lock(gs_critsect); wxCriticalSectionLocker lock(gs_critsect);
if ( !--gs_counter && !m_cancelled ) if ( !--gs_counter && !m_cancelled )
gs_cond.Signal(); gs_cond.Post();
} }
static void TestDetachedThreads() static void TestDetachedThreads()
@@ -4854,8 +4854,9 @@ static void TestThreadDelete()
class MyWaitingThread : public wxThread class MyWaitingThread : public wxThread
{ {
public: public:
MyWaitingThread(wxCondition *condition) MyWaitingThread( wxMutex *mutex, wxCondition *condition )
{ {
m_mutex = mutex;
m_condition = condition; m_condition = condition;
Create(); Create();
@@ -4866,12 +4867,14 @@ public:
printf("Thread %lu has started running.\n", GetId()); printf("Thread %lu has started running.\n", GetId());
fflush(stdout); fflush(stdout);
gs_cond.Signal(); gs_cond.Post();
printf("Thread %lu starts to wait...\n", GetId()); printf("Thread %lu starts to wait...\n", GetId());
fflush(stdout); fflush(stdout);
m_mutex->Lock();
m_condition->Wait(); m_condition->Wait();
m_mutex->Unlock();
printf("Thread %lu finished to wait, exiting.\n", GetId()); printf("Thread %lu finished to wait, exiting.\n", GetId());
fflush(stdout); fflush(stdout);
@@ -4880,17 +4883,19 @@ public:
} }
private: private:
wxMutex *m_mutex;
wxCondition *m_condition; wxCondition *m_condition;
}; };
static void TestThreadConditions() static void TestThreadConditions()
{ {
wxCondition condition; wxMutex mutex;
wxCondition condition(mutex);
// otherwise its difficult to understand which log messages pertain to // otherwise its difficult to understand which log messages pertain to
// which condition // which condition
wxLogTrace("thread", "Local condition var is %08x, gs_cond = %08x", //wxLogTrace("thread", "Local condition var is %08x, gs_cond = %08x",
condition.GetId(), gs_cond.GetId()); // condition.GetId(), gs_cond.GetId());
// create and launch threads // create and launch threads
MyWaitingThread *threads[10]; MyWaitingThread *threads[10];
@@ -4898,7 +4903,7 @@ static void TestThreadConditions()
size_t n; size_t n;
for ( n = 0; n < WXSIZEOF(threads); 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++ ) for ( n = 0; n < WXSIZEOF(threads); n++ )
@@ -4944,6 +4949,102 @@ static void TestThreadConditions()
wxThread::Sleep(500); 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 #endif // TEST_THREADS
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -5851,9 +5952,11 @@ int main(int argc, char **argv)
TestJoinableThreads(); TestJoinableThreads();
TestThreadSuspend(); TestThreadSuspend();
TestThreadDelete(); TestThreadDelete();
TestThreadConditions();
TestThreadExec();
} }
TestThreadConditions(); TestSemaphore();
#endif // TEST_THREADS #endif // TEST_THREADS
#ifdef TEST_TIMER #ifdef TEST_TIMER

View File

@@ -354,8 +354,7 @@ void wxSemaphore::Post()
class wxConditionInternal class wxConditionInternal
{ {
public: public:
wxConditionInternal( wxMutex *mutex ); wxConditionInternal(wxMutex& mutex);
~wxConditionInternal();
void Wait(); void Wait();
@@ -369,22 +368,18 @@ private:
int m_numWaiters; int m_numWaiters;
wxMutex m_mutexNumWaiters; wxMutex m_mutexNumWaiters;
wxMutex *m_mutex; wxMutex& m_mutex;
wxSemaphore m_semaphore; wxSemaphore m_semaphore;
}; };
wxConditionInternal::wxConditionInternal( wxMutex *mutex ) wxConditionInternal::wxConditionInternal(wxMutex& mutex)
: m_mutex(mutex)
{ {
m_mutex = mutex;
m_numWaiters = 0; m_numWaiters = 0;
} }
wxConditionInternal::~wxConditionInternal()
{
}
void wxConditionInternal::Wait() void wxConditionInternal::Wait()
{ {
// increment the number of waiters // increment the number of waiters
@@ -392,7 +387,7 @@ void wxConditionInternal::Wait()
m_numWaiters++; m_numWaiters++;
m_mutexNumWaiters.Unlock(); m_mutexNumWaiters.Unlock();
m_mutex->Unlock(); m_mutex.Unlock();
// a potential race condition can occur here // a potential race condition can occur here
// //
@@ -407,7 +402,7 @@ void wxConditionInternal::Wait()
// wait ( if necessary ) and decrement semaphore // wait ( if necessary ) and decrement semaphore
m_semaphore.Wait(); m_semaphore.Wait();
m_mutex->Lock(); m_mutex.Lock();
} }
bool wxConditionInternal::Wait( unsigned long timeout_millis ) bool wxConditionInternal::Wait( unsigned long timeout_millis )
@@ -416,7 +411,7 @@ bool wxConditionInternal::Wait( unsigned long timeout_millis )
m_numWaiters++; m_numWaiters++;
m_mutexNumWaiters.Unlock(); m_mutexNumWaiters.Unlock();
m_mutex->Unlock(); m_mutex.Unlock();
// a race condition can occur at this point in the code // 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_mutexNumWaiters.Unlock();
} }
m_mutex->Lock(); m_mutex.Lock();
return success; return success;
} }
@@ -489,18 +484,9 @@ void wxConditionInternal::Broadcast()
// wxCondition implementation // wxCondition implementation
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
wxCondition::wxCondition( wxMutex *mutex ) wxCondition::wxCondition(wxMutex& mutex)
{ {
if ( !mutex ) m_internal = new wxConditionInternal( mutex );
{
wxFAIL_MSG( _T("NULL mutex in wxCondition ctor") );
m_internal = NULL;
}
else
{
m_internal = new wxConditionInternal( mutex );
}
} }
wxCondition::~wxCondition() wxCondition::~wxCondition()
@@ -510,25 +496,22 @@ wxCondition::~wxCondition()
void wxCondition::Wait() void wxCondition::Wait()
{ {
if ( m_internal ) m_internal->Wait();
m_internal->Wait();
} }
bool wxCondition::Wait( unsigned long timeout_millis ) 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() void wxCondition::Signal()
{ {
if ( m_internal ) m_internal->Signal();
m_internal->Signal();
} }
void wxCondition::Broadcast() void wxCondition::Broadcast()
{ {
if ( m_internal ) m_internal->Broadcast();
m_internal->Broadcast();
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------

View File

@@ -319,7 +319,7 @@ wxMutexError wxMutex::Unlock()
class wxConditionInternal class wxConditionInternal
{ {
public: public:
wxConditionInternal( wxMutex *mutex ); wxConditionInternal(wxMutex& mutex);
~wxConditionInternal(); ~wxConditionInternal();
void Wait(); void Wait();
@@ -331,14 +331,16 @@ public:
void Broadcast(); void Broadcast();
private: 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; 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 ) if ( pthread_cond_init( &m_cond, NULL ) != 0 )
{ {
wxLogDebug(_T("pthread_cond_init() failed")); wxLogDebug(_T("pthread_cond_init() failed"));
@@ -355,7 +357,7 @@ wxConditionInternal::~wxConditionInternal()
void wxConditionInternal::Wait() 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")); wxLogDebug(_T("pthread_cond_wait() failed"));
} }
@@ -363,13 +365,14 @@ void wxConditionInternal::Wait()
bool wxConditionInternal::Wait( const timespec *ts ) bool wxConditionInternal::Wait( const timespec *ts )
{ {
int result = pthread_cond_timedwait( &m_cond, int result = pthread_cond_timedwait( &m_cond, GetMutex(), ts );
&(m_mutex->m_internal->m_mutex),
ts );
if ( result == ETIMEDOUT ) if ( result == ETIMEDOUT )
return FALSE; return FALSE;
wxASSERT_MSG( result == 0, _T("pthread_cond_timedwait() failed") ); if ( result != 0 )
{
wxLogDebug(_T("pthread_cond_timedwait() failed"));
}
return TRUE; return TRUE;
} }
@@ -397,18 +400,9 @@ void wxConditionInternal::Broadcast()
// wxCondition // wxCondition
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
wxCondition::wxCondition( wxMutex *mutex ) wxCondition::wxCondition(wxMutex& mutex)
{ {
if ( !mutex ) m_internal = new wxConditionInternal( mutex );
{
wxFAIL_MSG( _T("NULL mutex in wxCondition ctor") );
m_internal = NULL;
}
else
{
m_internal = new wxConditionInternal( mutex );
}
} }
wxCondition::~wxCondition() wxCondition::~wxCondition()
@@ -418,14 +412,11 @@ wxCondition::~wxCondition()
void wxCondition::Wait() void wxCondition::Wait()
{ {
if ( m_internal ) m_internal->Wait();
m_internal->Wait();
} }
bool wxCondition::Wait( unsigned long timeout_millis ) bool wxCondition::Wait( unsigned long timeout_millis )
{ {
wxCHECK_MSG( m_internal, FALSE, _T("can't wait on uninitalized condition") );
wxLongLong curtime = wxGetLocalTimeMillis(); wxLongLong curtime = wxGetLocalTimeMillis();
curtime += timeout_millis; curtime += timeout_millis;
wxLongLong temp = curtime / 1000; wxLongLong temp = curtime / 1000;
@@ -444,14 +435,12 @@ bool wxCondition::Wait( unsigned long timeout_millis )
void wxCondition::Signal() void wxCondition::Signal()
{ {
if ( m_internal ) m_internal->Signal();
m_internal->Signal();
} }
void wxCondition::Broadcast() void wxCondition::Broadcast()
{ {
if ( m_internal ) m_internal->Broadcast();
m_internal->Broadcast();
} }
// =========================================================================== // ===========================================================================
@@ -483,7 +472,7 @@ private:
}; };
wxSemaphoreInternal::wxSemaphoreInternal( int initialcount, int maxcount ) wxSemaphoreInternal::wxSemaphoreInternal( int initialcount, int maxcount )
: m_cond(&m_mutex) : m_cond(m_mutex)
{ {
if ( (initialcount < 0) || ((maxcount > 0) && (initialcount > maxcount)) ) if ( (initialcount < 0) || ((maxcount > 0) && (initialcount > maxcount)) )
@@ -602,7 +591,7 @@ public:
m_signaled = FALSE; m_signaled = FALSE;
m_mutex = new wxMutex(); m_mutex = new wxMutex();
m_cond = new wxCondition( m_mutex ); m_cond = new wxCondition( *m_mutex );
} }
// increment the reference count // increment the reference count
@@ -1711,7 +1700,7 @@ bool wxThreadModule::OnInit()
#endif // wxUSE_GUI #endif // wxUSE_GUI
gs_mutexDeleteThread = new wxMutex(); gs_mutexDeleteThread = new wxMutex();
gs_condAllDeleted = new wxCondition( gs_mutexDeleteThread ); gs_condAllDeleted = new wxCondition( *gs_mutexDeleteThread );
return TRUE; return TRUE;
} }