#if wxUSE_THREADS
// only for wxUSE_THREADS - otherwise we'd get undefined symbols
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(__APPLE__)
#pragma interface "thread.h"
#endif
#undef Yield
#endif
-#include "wx/module.h"
-
// ----------------------------------------------------------------------------
// constants
// ----------------------------------------------------------------------------
};
// forward declarations
-class WXDLLEXPORT wxConditionInternal;
-class WXDLLEXPORT wxMutexInternal;
-class WXDLLEXPORT wxSemaphoreInternal;
-class WXDLLEXPORT wxThreadInternal;
+class WXDLLIMPEXP_BASE wxThreadHelper;
+class WXDLLIMPEXP_BASE wxConditionInternal;
+class WXDLLIMPEXP_BASE wxMutexInternal;
+class WXDLLIMPEXP_BASE wxSemaphoreInternal;
+class WXDLLIMPEXP_BASE wxThreadInternal;
// ----------------------------------------------------------------------------
// A mutex object is a synchronization object whose state is set to signaled
// you should consider wxMutexLocker whenever possible instead of directly
// working with wxMutex class - it is safer
-class WXDLLEXPORT wxMutex
+class WXDLLIMPEXP_BASE wxMutex
{
public:
// constructor & destructor
// a helper class which locks the mutex in the ctor and unlocks it in the dtor:
// this ensures that mutex is always unlocked, even if the function returns or
// throws an exception before it reaches the end
-class WXDLLEXPORT wxMutexLocker
+class WXDLLIMPEXP_BASE wxMutexLocker
{
public:
// lock the mutex in the ctor
// just mutexes make all wxCriticalSection class functions inline
#if !defined(__WXMSW__) && !defined(__WXPM__)
#define wxCRITSECT_IS_MUTEX 1
+
+ #define wxCRITSECT_INLINE inline
#else // MSW || OS2
#define wxCRITSECT_IS_MUTEX 0
+
+ #define wxCRITSECT_INLINE
#endif // MSW/!MSW
// you should consider wxCriticalSectionLocker whenever possible instead of
// directly working with wxCriticalSection class - it is safer
-class WXDLLEXPORT wxCriticalSection
+class WXDLLIMPEXP_BASE wxCriticalSection
{
public:
// ctor & dtor
- wxCriticalSection();
- ~wxCriticalSection();
+ wxCRITSECT_INLINE wxCriticalSection();
+ wxCRITSECT_INLINE ~wxCriticalSection();
// enter the section (the same as locking a mutex)
- void Enter();
+ wxCRITSECT_INLINE void Enter();
// leave the critical section (same as unlocking a mutex)
- void Leave();
+ wxCRITSECT_INLINE void Leave();
private:
#if wxCRITSECT_IS_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
+ // 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
- char m_buffer[24];
+ //
+ // 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)
+ typedef char wxCritSectBuffer[24];
+ union
+ {
+ unsigned long m_dummy1;
+ void *m_dummy2;
+
+ wxCritSectBuffer m_buffer;
+ };
#else
// nothing for OS/2
#endif // Unix/Win32/OS2
#if wxCRITSECT_IS_MUTEX
// implement wxCriticalSection using mutexes
- wxCriticalSection::wxCriticalSection() { }
- wxCriticalSection::~wxCriticalSection() { }
+ inline wxCriticalSection::wxCriticalSection() { }
+ inline wxCriticalSection::~wxCriticalSection() { }
- void wxCriticalSection::Enter() { (void)m_mutex.Lock(); }
- void wxCriticalSection::Leave() { (void)m_mutex.Unlock(); }
+ 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 th mutexes
-class WXDLLEXPORT wxCriticalSectionLocker
+class WXDLLIMPEXP_BASE wxCriticalSectionLocker
{
public:
wxCriticalSectionLocker(wxCriticalSection& cs)
// thread(s) to wait until some condition is fulfilled
// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxCondition
+class WXDLLIMPEXP_BASE wxCondition
{
public:
// Each wxCondition object is associated with a (single) wxMutex object.
// a shared resource
// ----------------------------------------------------------------------------
-class WXDLLEXPORT wxSemaphore
+class WXDLLIMPEXP_BASE wxSemaphore
{
public:
// specifying a maxcount of 0 actually makes wxSemaphore behave as if there
typedef unsigned long wxThreadIdType;
#endif
-class WXDLLEXPORT wxThread
+class WXDLLIMPEXP_BASE wxThread
{
public:
// the return type for the thread function
bool m_isDetached;
};
+// wxThreadHelperThread class
+// --------------------------
+
+class WXDLLIMPEXP_BASE wxThreadHelperThread : public wxThread
+{
+public:
+ // constructor only creates the C++ thread object and doesn't create (or
+ // start) the real thread
+ wxThreadHelperThread(wxThreadHelper& owner)
+ : wxThread(wxTHREAD_JOINABLE), m_owner(owner)
+ { }
+
+protected:
+ // entry point for the thread -- calls Entry() in owner.
+ virtual void *Entry();
+
+private:
+ // the owner of the thread
+ wxThreadHelper& m_owner;
+
+ // no copy ctor/assignment operator
+ wxThreadHelperThread(const wxThreadHelperThread&);
+ wxThreadHelperThread& operator=(const wxThreadHelperThread&);
+};
+
+// ----------------------------------------------------------------------------
+// wxThreadHelper: this class implements the threading logic to run a
+// background task in another object (such as a window). It is a mix-in: just
+// derive from it to implement a threading background task in your class.
+// ----------------------------------------------------------------------------
+
+class WXDLLIMPEXP_BASE wxThreadHelper
+{
+private:
+ void KillThread()
+ {
+ if ( m_thread )
+ {
+ m_thread->Kill();
+ delete m_thread;
+ }
+ }
+
+public:
+ // constructor only initializes m_thread to NULL
+ wxThreadHelper() : m_thread(NULL) { }
+
+ // destructor deletes m_thread
+ virtual ~wxThreadHelper() { KillThread(); }
+
+ // create a new thread (and optionally set the stack size on platforms that
+ // support/need that), call Run() to start it
+ wxThreadError Create(unsigned int stackSize = 0)
+ {
+ KillThread();
+
+ m_thread = new wxThreadHelperThread(*this);
+
+ return m_thread->Create(stackSize);
+ }
+
+ // entry point for the thread - called by Run() and executes in the context
+ // of this thread.
+ virtual void *Entry() = 0;
+
+ // returns a pointer to the thread which can be used to call Run()
+ wxThread *GetThread() const { return m_thread; }
+
+protected:
+ wxThread *m_thread;
+};
+
+// call Entry() in owner, put it down here to avoid circular declarations
+inline void *wxThreadHelperThread::Entry()
+{
+ return m_owner.Entry();
+}
+
// ----------------------------------------------------------------------------
// Automatic initialization
// ----------------------------------------------------------------------------
// GUI mutex handling.
-void WXDLLEXPORT wxMutexGuiEnter();
-void WXDLLEXPORT wxMutexGuiLeave();
+void WXDLLIMPEXP_BASE wxMutexGuiEnter();
+void WXDLLIMPEXP_BASE wxMutexGuiLeave();
// macros for entering/leaving critical sections which may be used without
// having to take them inside "#if wxUSE_THREADS"
#define wxENTER_CRIT_SECT(cs) (cs).Enter()
#define wxLEAVE_CRIT_SECT(cs) (cs).Leave()
#define wxCRIT_SECT_DECLARE(cs) static wxCriticalSection cs
+#define wxCRIT_SECT_DECLARE_MEMBER(cs) wxCriticalSection cs
#define wxCRIT_SECT_LOCKER(name, cs) wxCriticalSectionLocker name(cs)
+// function for checking if we're in the main thread which may be used whether
+// wxUSE_THREADS is 0 or 1
+inline bool wxIsMainThread() { return wxThread::IsMain(); }
+
#else // !wxUSE_THREADS
// no thread support
-inline void WXDLLEXPORT wxMutexGuiEnter() { }
-inline void WXDLLEXPORT wxMutexGuiLeave() { }
+inline void WXDLLIMPEXP_BASE wxMutexGuiEnter() { }
+inline void WXDLLIMPEXP_BASE wxMutexGuiLeave() { }
// macros for entering/leaving critical sections which may be used without
// having to take them inside "#if wxUSE_THREADS"
#define wxENTER_CRIT_SECT(cs)
#define wxLEAVE_CRIT_SECT(cs)
#define wxCRIT_SECT_DECLARE(cs)
+#define wxCRIT_SECT_DECLARE_MEMBER(cs)
#define wxCRIT_SECT_LOCKER(name, cs)
+// if there is only one thread, it is always the main one
+inline bool wxIsMainThread() { return true; }
+
#endif // wxUSE_THREADS/!wxUSE_THREADS
// mark part of code as being a critical section: this macro declares a
wxCRIT_SECT_LOCKER(cs##name##Locker, s_cs##name)
// automatically lock GUI mutex in ctor and unlock it in dtor
-class WXDLLEXPORT wxMutexGuiLocker
+class WXDLLIMPEXP_BASE wxMutexGuiLocker
{
public:
wxMutexGuiLocker() { wxMutexGuiEnter(); }
// unlock GUI if there are threads waiting for and lock it back when
// there are no more of them - should be called periodically by the main
// thread
- extern void WXDLLEXPORT wxMutexGuiLeaveOrEnter();
+ extern void WXDLLIMPEXP_BASE wxMutexGuiLeaveOrEnter();
// returns TRUE if the main thread has GUI lock
- extern bool WXDLLEXPORT wxGuiOwnedByMainThread();
+ extern bool WXDLLIMPEXP_BASE wxGuiOwnedByMainThread();
#ifndef __WXPM__
// wakes up the main thread if it's sleeping inside ::GetMessage()
- extern void WXDLLEXPORT wxWakeUpMainThread();
+ extern void WXDLLIMPEXP_BASE wxWakeUpMainThread();
#endif // !OS/2
// return TRUE if the main thread is waiting for some other to terminate:
// wxApp then should block all "dangerous" messages
- extern bool WXDLLEXPORT wxIsWaitingForThread();
+ extern bool WXDLLIMPEXP_BASE wxIsWaitingForThread();
#endif // MSW, Mac, OS/2
#endif // wxUSE_THREADS