X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9e84b84742248ef54a561b4937bbc039332c2c51..bf95a04f16759468ee7af83a7a78019399c648bb:/include/wx/thread.h diff --git a/include/wx/thread.h b/include/wx/thread.h index 9917e594df..543f16ceda 100644 --- a/include/wx/thread.h +++ b/include/wx/thread.h @@ -23,7 +23,7 @@ #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 @@ -32,8 +32,6 @@ #undef Yield #endif -#include "wx/module.h" - // ---------------------------------------------------------------------------- // constants // ---------------------------------------------------------------------------- @@ -116,10 +114,11 @@ enum wxMutexType }; // 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 @@ -130,7 +129,7 @@ class WXDLLEXPORT wxThreadInternal; // 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 @@ -173,7 +172,7 @@ protected: // 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 @@ -212,24 +211,28 @@ private: // 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 - inline wxCriticalSection(); - inline ~wxCriticalSection(); + wxCRITSECT_INLINE wxCriticalSection(); + wxCRITSECT_INLINE ~wxCriticalSection(); // enter the section (the same as locking a mutex) - inline void Enter(); + wxCRITSECT_INLINE void Enter(); // leave the critical section (same as unlocking a mutex) - inline void Leave(); + wxCRITSECT_INLINE void Leave(); private: #if wxCRITSECT_IS_MUTEX @@ -237,11 +240,23 @@ private: #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 @@ -258,9 +273,12 @@ private: 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) @@ -285,7 +303,7 @@ private: // 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. @@ -347,7 +365,7 @@ private: // a shared resource // ---------------------------------------------------------------------------- -class WXDLLEXPORT wxSemaphore +class WXDLLIMPEXP_BASE wxSemaphore { public: // specifying a maxcount of 0 actually makes wxSemaphore behave as if there @@ -402,7 +420,7 @@ private: typedef unsigned long wxThreadIdType; #endif -class WXDLLEXPORT wxThread +class WXDLLIMPEXP_BASE wxThread { public: // the return type for the thread function @@ -564,38 +582,146 @@ private: 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 +// critical section with the given name and enters it immediately and leaves +// it at the end of the current scope +// +// example: +// +// int Count() +// { +// static int s_counter = 0; +// +// wxCRITICAL_SECTION(counter); +// +// return ++s_counter; +// } +// +// this function is MT-safe in presence of the threads but there is no +// overhead when the library is compiled without threads +#define wxCRITICAL_SECTION(name) \ + wxCRIT_SECT_DECLARE(s_cs##name); \ + 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(); } @@ -612,19 +738,19 @@ public: // 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