X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/4562f6852f3157b9e9d2856a413c6b17da58896b..b3fcfa4d89d44425ed28050462c6064100fe7b05:/include/wx/thread.h diff --git a/include/wx/thread.h b/include/wx/thread.h index f4fec4683c..1e7d9f215e 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(NO_GCC_PRAGMA) #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 @@ -210,26 +209,30 @@ private: // in order to avoid any overhead under platforms where critical sections are // just mutexes make all wxCriticalSection class functions inline -#if !defined(__WXMSW__) && !defined(__WXPM__) +#if !defined(__WXMSW__) #define wxCRITSECT_IS_MUTEX 1 -#else // MSW || OS2 + + #define wxCRITSECT_INLINE inline +#else // MSW #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,14 +240,28 @@ 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]; -#else - // nothing for OS/2 -#endif // Unix/Win32/OS2 + // + // 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 DECLARE_NO_COPY_CLASS(wxCriticalSection) }; @@ -258,9 +275,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 +305,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 +367,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 +422,7 @@ private: typedef unsigned long wxThreadIdType; #endif -class WXDLLEXPORT wxThread +class WXDLLIMPEXP_BASE wxThread { public: // the return type for the thread function @@ -564,34 +584,121 @@ 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 @@ -616,7 +723,7 @@ inline void WXDLLEXPORT wxMutexGuiLeave() { } 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(); } @@ -629,23 +736,23 @@ public: #if wxUSE_THREADS -#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXPM__) +#if defined(__WXMSW__) || defined(__WXMAC__) || defined(__WXPM__) || defined(__EMX__) // 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