int main()
{
wxMutex mutex;
- wxCondition condition(&mutex);
+ wxCondition condition(mutex);
for ( int i = 0; i < 10; i++ )
{
\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}}
// 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();
#undef TEST_ALL
static const bool TEST_ALL = TRUE;
#else
- #define TEST_FILENAME
+ #define TEST_THREADS
static const bool TEST_ALL = FALSE;
#endif
static size_t gs_counter = (size_t)-1;
static wxCriticalSection gs_critsect;
-static wxCondition gs_cond;
+static wxSemaphore gs_cond;
class MyJoinableThread : public wxThread
{
wxCriticalSectionLocker lock(gs_critsect);
if ( !--gs_counter && !m_cancelled )
- gs_cond.Signal();
+ gs_cond.Post();
}
static void TestDetachedThreads()
class MyWaitingThread : public wxThread
{
public:
- MyWaitingThread(wxCondition *condition)
+ MyWaitingThread( wxMutex *mutex, wxCondition *condition )
{
+ m_mutex = mutex;
m_condition = condition;
Create();
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);
}
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];
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++ )
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
// ----------------------------------------------------------------------------
TestJoinableThreads();
TestThreadSuspend();
TestThreadDelete();
+ TestThreadConditions();
+ TestThreadExec();
}
- TestThreadConditions();
+ TestSemaphore();
#endif // TEST_THREADS
#ifdef TEST_TIMER
class wxConditionInternal
{
public:
- wxConditionInternal( wxMutex *mutex );
- ~wxConditionInternal();
+ wxConditionInternal(wxMutex& mutex);
void Wait();
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
m_numWaiters++;
m_mutexNumWaiters.Unlock();
- m_mutex->Unlock();
+ m_mutex.Unlock();
// a potential race condition can occur here
//
// wait ( if necessary ) and decrement semaphore
m_semaphore.Wait();
- m_mutex->Lock();
+ m_mutex.Lock();
}
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
//
m_mutexNumWaiters.Unlock();
}
- m_mutex->Lock();
+ m_mutex.Lock();
return success;
}
// 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()
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();
}
// ----------------------------------------------------------------------------
class wxConditionInternal
{
public:
- wxConditionInternal( wxMutex *mutex );
+ wxConditionInternal(wxMutex& mutex);
~wxConditionInternal();
void Wait();
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"));
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"));
}
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;
}
// 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()
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;
void wxCondition::Signal()
{
- if ( m_internal )
- m_internal->Signal();
+ m_internal->Signal();
}
void wxCondition::Broadcast()
{
- if ( m_internal )
- m_internal->Broadcast();
+ m_internal->Broadcast();
}
// ===========================================================================
};
wxSemaphoreInternal::wxSemaphoreInternal( int initialcount, int maxcount )
- : m_cond(&m_mutex)
+ : m_cond(m_mutex)
{
if ( (initialcount < 0) || ((maxcount > 0) && (initialcount > maxcount)) )
m_signaled = FALSE;
m_mutex = new wxMutex();
- m_cond = new wxCondition( m_mutex );
+ m_cond = new wxCondition( *m_mutex );
}
// increment the reference count
#endif // wxUSE_GUI
gs_mutexDeleteThread = new wxMutex();
- gs_condAllDeleted = new wxCondition( gs_mutexDeleteThread );
+ gs_condAllDeleted = new wxCondition( *gs_mutexDeleteThread );
return TRUE;
}