+ // lock the mutex in the ctor
+ wxMutexLocker(wxMutex& mutex)
+ : m_isOk(false), m_mutex(mutex)
+ { m_isOk = ( m_mutex.Lock() == wxMUTEX_NO_ERROR ); }
+
+ // returns true if mutex was successfully locked in ctor
+ bool IsOk() const
+ { return m_isOk; }
+
+ // unlock the mutex in dtor
+ ~wxMutexLocker()
+ { if ( IsOk() ) m_mutex.Unlock(); }
+
+private:
+ // no assignment operator nor copy ctor
+ wxMutexLocker(const wxMutexLocker&);
+ wxMutexLocker& operator=(const wxMutexLocker&);
+
+ bool m_isOk;
+ wxMutex& m_mutex;
+};
+
+// ----------------------------------------------------------------------------
+// Critical section: this is the same as mutex but is only visible to the
+// threads of the same process. For the platforms which don't have native
+// support for critical sections, they're implemented entirely in terms of
+// mutexes.
+//
+// NB: wxCriticalSection object does not allocate any memory in its ctor
+// which makes it possible to have static globals of this class
+// ----------------------------------------------------------------------------
+
+// in order to avoid any overhead under platforms where critical sections are
+// just mutexes make all wxCriticalSection class functions inline
+#if !defined(__WINDOWS__)
+ #define wxCRITSECT_IS_MUTEX 1
+
+ #define wxCRITSECT_INLINE WXEXPORT inline
+#else // MSW
+ #define wxCRITSECT_IS_MUTEX 0
+
+ #define wxCRITSECT_INLINE
+#endif // MSW/!MSW
+
+enum wxCriticalSectionType
+{
+ // recursive critical section
+ wxCRITSEC_DEFAULT,
+
+ // non-recursive critical section
+ wxCRITSEC_NON_RECURSIVE
+};
+
+// you should consider wxCriticalSectionLocker whenever possible instead of
+// directly working with wxCriticalSection class - it is safer
+class WXDLLIMPEXP_BASE wxCriticalSection
+{
+public:
+ // ctor & dtor
+ wxCRITSECT_INLINE wxCriticalSection( wxCriticalSectionType critSecType = wxCRITSEC_DEFAULT );
+ wxCRITSECT_INLINE ~wxCriticalSection();
+ // enter the section (the same as locking a mutex)
+ wxCRITSECT_INLINE void Enter();
+
+ // try to enter the section (the same as trying to lock a mutex)
+ wxCRITSECT_INLINE bool TryEnter();
+
+ // leave the critical section (same as unlocking a mutex)
+ wxCRITSECT_INLINE void Leave();
+
+private:
+#if wxCRITSECT_IS_MUTEX
+ wxMutex m_mutex;
+#elif defined(__WINDOWS__)
+ // we can't allocate any memory in the ctor, so use placement new -
+ // unfortunately, we have to hardcode the sizeof() here because we can't
+ // include windows.h from this public header and we also have to use the
+ // union to force the correct (i.e. maximal) alignment
+ //
+ // if CRITICAL_SECTION size changes in Windows, you'll get an assert from
+ // thread.cpp and will need to increase the buffer size
+#ifdef __WIN64__
+ typedef char wxCritSectBuffer[40];
+#else // __WIN32__
+ typedef char wxCritSectBuffer[24];
+#endif
+ union
+ {
+ unsigned long m_dummy1;
+ void *m_dummy2;
+
+ wxCritSectBuffer m_buffer;
+ };
+#endif // Unix&OS2/Win32
+
+ wxDECLARE_NO_COPY_CLASS(wxCriticalSection);
+};
+
+#if wxCRITSECT_IS_MUTEX
+ // implement wxCriticalSection using mutexes
+ inline wxCriticalSection::wxCriticalSection( wxCriticalSectionType critSecType )
+ : m_mutex( critSecType == wxCRITSEC_DEFAULT ? wxMUTEX_RECURSIVE : wxMUTEX_DEFAULT ) { }
+ inline wxCriticalSection::~wxCriticalSection() { }
+
+ inline void wxCriticalSection::Enter() { (void)m_mutex.Lock(); }
+ inline bool wxCriticalSection::TryEnter() { return m_mutex.TryLock() == wxMUTEX_NO_ERROR; }
+ inline void wxCriticalSection::Leave() { (void)m_mutex.Unlock(); }
+#endif // wxCRITSECT_IS_MUTEX
+
+#undef wxCRITSECT_INLINE
+#undef wxCRITSECT_IS_MUTEX
+
+// wxCriticalSectionLocker is the same to critical sections as wxMutexLocker is
+// to mutexes
+class WXDLLIMPEXP_BASE wxCriticalSectionLocker
+{
+public:
+ wxCriticalSectionLocker(wxCriticalSection& cs)
+ : m_critsect(cs)
+ {
+ m_critsect.Enter();
+ }
+
+ ~wxCriticalSectionLocker()
+ {
+ m_critsect.Leave();
+ }
+
+private:
+ wxCriticalSection& m_critsect;
+
+ wxDECLARE_NO_COPY_CLASS(wxCriticalSectionLocker);
+};
+
+// ----------------------------------------------------------------------------
+// wxCondition models a POSIX condition variable which allows one (or more)
+// thread(s) to wait until some condition is fulfilled
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_BASE wxCondition
+{
+public:
+ // Each wxCondition object is associated with a (single) wxMutex object.
+ // The mutex object MUST be locked before calling Wait()
+ wxCondition(wxMutex& mutex);
+
+ // dtor is not virtual, don't use this class polymorphically
+ ~wxCondition();
+
+ // return true if the condition has been created successfully
+ bool IsOk() const;
+
+ // NB: the associated mutex MUST be locked beforehand by the calling thread
+ //
+ // it atomically releases the lock on the associated mutex
+ // and starts waiting to be woken up by a Signal()/Broadcast()
+ // once its signaled, then it will wait until it can reacquire
+ // the lock on the associated mutex object, before returning.
+ wxCondError Wait();
+
+ // exactly as Wait() except that it may also return if the specified
+ // timeout elapses even if the condition hasn't been signalled: in this
+ // case, the return value is false, otherwise (i.e. in case of a normal
+ // return) it is true
+ //
+ // the timeout parameter specifies an interval that needs to be waited for
+ // in milliseconds
+ wxCondError WaitTimeout(unsigned long milliseconds);
+
+ // NB: the associated mutex may or may not be locked by the calling thread
+ //
+ // this method unblocks one thread if any are blocking on the condition.
+ // if no thread is blocking in Wait(), then the signal is NOT remembered
+ // The thread which was blocking on Wait() will then reacquire the lock
+ // on the associated mutex object before returning
+ wxCondError Signal();
+
+ // NB: the associated mutex may or may not be locked by the calling thread
+ //
+ // this method unblocks all threads if any are blocking on the condition.
+ // if no thread is blocking in Wait(), then the signal is NOT remembered
+ // The threads which were blocking on Wait() will then reacquire the lock
+ // on the associated mutex object before returning.
+ wxCondError Broadcast();
+
+
+#if WXWIN_COMPATIBILITY_2_6
+ // deprecated version, don't use
+ wxDEPRECATED( bool Wait(unsigned long milliseconds) );
+#endif // WXWIN_COMPATIBILITY_2_6
+
+private:
+ wxConditionInternal *m_internal;
+
+ wxDECLARE_NO_COPY_CLASS(wxCondition);
+};
+
+#if WXWIN_COMPATIBILITY_2_6
+ inline bool wxCondition::Wait(unsigned long milliseconds)
+ { return WaitTimeout(milliseconds) == wxCOND_NO_ERROR; }
+#endif // WXWIN_COMPATIBILITY_2_6
+
+// ----------------------------------------------------------------------------
+// wxSemaphore: a counter limiting the number of threads concurrently accessing
+// a shared resource
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_BASE wxSemaphore
+{
+public:
+ // specifying a maxcount of 0 actually makes wxSemaphore behave as if there
+ // is no upper limit, if maxcount is 1 the semaphore behaves as a mutex
+ wxSemaphore( int initialcount = 0, int maxcount = 0 );
+
+ // dtor is not virtual, don't use this class polymorphically
+ ~wxSemaphore();
+
+ // return true if the semaphore has been created successfully
+ bool IsOk() const;
+
+ // wait indefinitely, until the semaphore count goes beyond 0
+ // and then decrement it and return (this method might have been called
+ // Acquire())
+ wxSemaError Wait();
+
+ // same as Wait(), but does not block, returns wxSEMA_NO_ERROR if
+ // successful and wxSEMA_BUSY if the count is currently zero
+ wxSemaError TryWait();
+
+ // same as Wait(), but as a timeout limit, returns wxSEMA_NO_ERROR if the
+ // semaphore was acquired and wxSEMA_TIMEOUT if the timeout has elapsed
+ wxSemaError WaitTimeout(unsigned long milliseconds);
+
+ // increments the semaphore count and signals one of the waiting threads
+ wxSemaError Post();
+