// 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:
// 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
{
// 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
// 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
//
#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
// 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:
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 )
{
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()
"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);
// 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;
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
// wait interrupted or timeout elapsed
ok = FALSE;
}
+ WaitDone(ownmutexnode);
}
else
{
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();
}
}
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)
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();
}
// -----------------------------------------------------------------------------