cannam@62: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ cannam@62: cannam@62: /* cannam@62: QM DSP Library cannam@62: cannam@62: Centre for Digital Music, Queen Mary, University of London. cannam@62: This file copyright Chris Cannam, used with permission. cannam@62: */ cannam@62: cannam@62: #ifndef _THREAD_H_ cannam@62: #define _THREAD_H_ cannam@62: cannam@62: #ifdef _WIN32 cannam@62: #include cannam@62: #else /* !_WIN32 */ cannam@62: #ifdef USE_PTHREADS cannam@62: #include cannam@62: #endif /* USE_PTHREADS */ cannam@62: #endif /* !_WIN32 */ cannam@62: cannam@62: #include cannam@62: cannam@62: //#define DEBUG_THREAD 1 cannam@62: //#define DEBUG_MUTEX 1 cannam@62: //#define DEBUG_CONDITION 1 cannam@62: cannam@62: class Thread cannam@62: { cannam@62: public: cannam@62: #ifdef _WIN32 cannam@62: typedef HANDLE Id; cannam@62: #else cannam@62: #ifdef USE_PTHREADS cannam@62: typedef pthread_t Id; cannam@62: #endif cannam@62: #endif cannam@62: cannam@62: Thread(); cannam@62: virtual ~Thread(); cannam@62: cannam@62: Id id(); cannam@62: cannam@62: void start(); cannam@62: void wait(); cannam@62: cannam@62: static bool threadingAvailable(); cannam@62: cannam@62: protected: cannam@62: virtual void run() = 0; cannam@62: cannam@62: private: cannam@62: #ifdef _WIN32 cannam@62: HANDLE m_id; cannam@62: bool m_extant; cannam@62: static DWORD WINAPI staticRun(LPVOID lpParam); cannam@62: #else cannam@62: #ifdef USE_PTHREADS cannam@62: pthread_t m_id; cannam@62: bool m_extant; cannam@62: static void *staticRun(void *); cannam@62: #endif cannam@62: #endif cannam@62: }; cannam@62: cannam@62: class Mutex cannam@62: { cannam@62: public: cannam@62: Mutex(); cannam@62: ~Mutex(); cannam@62: cannam@62: void lock(); cannam@62: void unlock(); cannam@62: bool trylock(); cannam@62: cannam@62: private: cannam@62: #ifdef _WIN32 cannam@62: HANDLE m_mutex; cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: DWORD m_lockedBy; cannam@62: #endif cannam@62: #else cannam@62: #ifdef USE_PTHREADS cannam@62: pthread_mutex_t m_mutex; cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: pthread_t m_lockedBy; cannam@62: bool m_locked; cannam@62: #endif cannam@62: #endif cannam@62: #endif cannam@62: }; cannam@62: cannam@62: class MutexLocker cannam@62: { cannam@62: public: cannam@62: MutexLocker(Mutex *); cannam@62: ~MutexLocker(); cannam@62: cannam@62: private: cannam@62: Mutex *m_mutex; cannam@62: }; cannam@62: cannam@62: class Condition cannam@62: { cannam@62: public: cannam@62: Condition(std::string name); cannam@62: ~Condition(); cannam@62: cannam@62: //!!! NO -- reproducing more conventional lock/wait cannam@62: cannam@62: // To wait on a condition, either simply call wait(), or call cannam@62: // lock() and then wait() (perhaps testing some state in between). cannam@62: // To signal a condition, call signal(). cannam@62: cannam@62: // Although any thread may signal on a given condition, only one cannam@62: // thread should ever wait on any given condition object -- cannam@62: // otherwise there will be a race conditions in the logic that cannam@62: // avoids the thread code having to track whether the condition's cannam@62: // mutex is locked or not. If that is your requirement, this cannam@62: // Condition wrapper is not for you. cannam@62: void lock(); cannam@62: void unlock(); cannam@62: void wait(int us = 0); cannam@62: cannam@62: void signal(); cannam@62: cannam@62: private: cannam@62: cannam@62: #ifdef _WIN32 cannam@62: HANDLE m_mutex; cannam@62: HANDLE m_condition; cannam@62: bool m_locked; cannam@62: #else cannam@62: #ifdef USE_PTHREADS cannam@62: pthread_mutex_t m_mutex; cannam@62: pthread_cond_t m_condition; cannam@62: bool m_locked; cannam@62: #endif cannam@62: #endif cannam@62: #ifdef DEBUG_CONDITION cannam@62: std::string m_name; cannam@62: #endif cannam@62: }; cannam@62: cannam@62: #endif