+ #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();
+
+ // leave the critical section (same as unlocking a mutex)
+ wxCRITSECT_INLINE void Leave();
+
+private:
+#if wxCRITSECT_IS_MUTEX
+ wxMutex m_mutex;
+#elif defined(__WXMSW__)
+ // 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
+ //
+ // finally, we need this typedef instead of declaring m_buffer directly
+ // because otherwise the assert mentioned above wouldn't compile with some
+ // compilers (notably CodeWarrior 8)
+#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 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);