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