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@359: #else c@359: #error Must have either _WIN32 or USE_PTHREADS defined 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@288: // Condition bundles a pthread-style condition variable and mutex c@288: // into one class. c@287: c@288: // To wait on a condition, call lock(), test termination variables c@288: // as appropriate, and then wait(). The condition will be c@288: // unlocked for the duration of the wait() call, which will end c@288: // when the condition is signalled. The condition will be locked c@288: // again when wait() returns. c@288: // c@288: // To signal a condition, call signal(). If the waiting thread c@288: // will be performing tests between its own lock() and wait(), c@288: // then the signalling thread should also lock() before it signals c@288: // (and then unlock afterwards). If the signalling thread always c@288: // locks the mutex during signalling, then the waiting thread c@288: // knows that signals will only happen during wait() and not be c@288: // missed at other times. c@288: 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