+// ===========================================================================
+// wxSemaphore implementation
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// wxSemaphoreInternal
+// ---------------------------------------------------------------------------
+
+class wxSemaphoreInternal
+{
+public:
+ wxSemaphoreInternal( int initialcount, int maxcount );
+
+ void Wait();
+ bool TryWait();
+
+ bool Wait( unsigned long timeout_millis );
+
+ void Post();
+
+private:
+ wxMutex m_mutex;
+ wxCondition m_cond;
+
+ int count,
+ maxcount;
+};
+
+wxSemaphoreInternal::wxSemaphoreInternal( int initialcount, int maxcount )
+ : m_cond(m_mutex)
+{
+
+ if ( (initialcount < 0) || ((maxcount > 0) && (initialcount > maxcount)) )
+ {
+ wxFAIL_MSG( _T("wxSemaphore: invalid initial count") );
+ }
+
+ maxcount = maxcount;
+ count = initialcount;
+}
+
+void wxSemaphoreInternal::Wait()
+{
+ wxMutexLocker locker(m_mutex);
+
+ while ( count <= 0 )
+ {
+ m_cond.Wait();
+ }
+
+ count--;
+}
+
+bool wxSemaphoreInternal::TryWait()
+{
+ wxMutexLocker locker(m_mutex);
+
+ if ( count <= 0 )
+ return FALSE;
+
+ count--;
+
+ return TRUE;
+}
+
+bool wxSemaphoreInternal::Wait( unsigned long timeout_millis )
+{
+ wxMutexLocker locker(m_mutex);
+
+ wxLongLong startTime = wxGetLocalTimeMillis();
+
+ while ( count <= 0 )
+ {
+ wxLongLong elapsed = wxGetLocalTimeMillis() - startTime;
+ long remainingTime = (long)timeout_millis - (long)elapsed.GetLo();
+ if ( remainingTime <= 0 )
+ return FALSE;
+
+ bool result = m_cond.Wait( remainingTime );
+ if ( !result )
+ return FALSE;
+ }
+
+ count--;
+
+ return TRUE;
+}
+
+void wxSemaphoreInternal::Post()
+{
+ wxMutexLocker locker(m_mutex);
+
+ if ( maxcount > 0 && count == maxcount )
+ {
+ wxFAIL_MSG( _T("wxSemaphore::Post() overflow") );
+ }
+
+ count++;
+
+ m_cond.Signal();
+}
+
+// --------------------------------------------------------------------------
+// wxSemaphore
+// --------------------------------------------------------------------------
+
+wxSemaphore::wxSemaphore( int initialcount, int maxcount )
+{
+ m_internal = new wxSemaphoreInternal( initialcount, maxcount );
+}
+
+wxSemaphore::~wxSemaphore()
+{
+ delete m_internal;
+}
+
+void wxSemaphore::Wait()
+{
+ m_internal->Wait();
+}
+
+bool wxSemaphore::TryWait()
+{
+ return m_internal->TryWait();
+}
+
+bool wxSemaphore::Wait( unsigned long timeout_millis )
+{
+ return m_internal->Wait( timeout_millis );
+}
+
+void wxSemaphore::Post()
+{
+ m_internal->Post();
+}
+
+// This class is used by wxThreadInternal to support Delete() on
+// a detached thread
+class wxRefCountedCondition
+{
+public:
+ // start with a initial reference count of 1
+ wxRefCountedCondition()
+ {
+ m_refCount = 1;
+ m_signaled = FALSE;
+
+ m_mutex = new wxMutex();
+ m_cond = new wxCondition( *m_mutex );
+ }
+
+ // increment the reference count
+ void AddRef()
+ {
+ wxMutexLocker locker( *m_mutex );
+
+ m_refCount++;
+ }
+
+ // decrement the reference count if reference count is zero then delete the
+ // object
+ void DeleteRef()
+ {
+ bool shouldDelete = FALSE;
+
+ m_mutex->Lock();
+
+ if ( --m_refCount == 0 )
+ {
+ shouldDelete = TRUE;
+ }
+
+ m_mutex->Unlock();
+
+ if ( shouldDelete )
+ {
+ delete this;
+ }
+ }
+
+
+ // sets the object to signaled this signal will be a persistent signal all
+ // further Wait()s on the object will return without blocking
+ void SetSignaled()
+ {
+ wxMutexLocker locker( *m_mutex );
+
+ m_signaled = TRUE;
+
+ m_cond->Broadcast();
+ }
+
+ // wait till the object is signaled if the object was already signaled then
+ // return immediately
+ void Wait()
+ {
+ wxMutexLocker locker( *m_mutex );
+
+ if ( !m_signaled )
+ {
+ m_cond->Wait();
+ }
+ }
+
+private:
+ int m_refCount;
+
+ wxMutex *m_mutex;
+ wxCondition *m_cond;
+
+ bool m_signaled;
+
+ // Cannot delete this object directly, call DeleteRef() instead
+ ~wxRefCountedCondition()
+ {
+ delete m_cond;
+ delete m_mutex;
+ }
+
+ // suppress gcc warning about the class having private dtor and not having
+ // friend (so what??)
+ friend class wxDummyFriend;
+};
+
+// ===========================================================================
+// wxThread implementation
+// ===========================================================================
+
+// the thread callback functions must have the C linkage
+extern "C"
+{
+
+#if HAVE_THREAD_CLEANUP_FUNCTIONS
+ // thread exit function
+ void wxPthreadCleanup(void *ptr);
+#endif // HAVE_THREAD_CLEANUP_FUNCTIONS
+
+void *wxPthreadStart(void *ptr);
+
+} // extern "C"
+
+// ----------------------------------------------------------------------------
+// wxThreadInternal
+// ----------------------------------------------------------------------------