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