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: #include "Thread.h" cannam@62: cannam@62: #include cannam@62: #include cannam@62: cannam@62: #ifdef USE_PTHREADS cannam@62: #include cannam@62: #include cannam@62: #endif cannam@62: cannam@62: using std::cerr; cannam@62: using std::endl; cannam@62: using std::string; cannam@62: cannam@62: #ifdef _WIN32 cannam@62: cannam@62: Thread::Thread() : cannam@62: m_id(0), cannam@62: m_extant(false) cannam@62: { cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Created thread object " << this << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: Thread::~Thread() cannam@62: { cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Destroying thread object " << this << ", id " << m_id << endl; cannam@62: #endif cannam@62: if (m_extant) { cannam@62: WaitForSingleObject(m_id, INFINITE); cannam@62: } cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Destroyed thread object " << this << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: void cannam@62: Thread::start() cannam@62: { cannam@62: m_id = CreateThread(NULL, 0, staticRun, this, 0, 0); cannam@62: if (!m_id) { cannam@62: cerr << "ERROR: thread creation failed" << endl; cannam@62: exit(1); cannam@62: } else { cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Created thread " << m_id << " for thread object " << this << endl; cannam@62: #endif cannam@62: m_extant = true; cannam@62: } cannam@62: } cannam@62: cannam@62: void cannam@62: Thread::wait() cannam@62: { cannam@62: if (m_extant) { cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Waiting on thread " << m_id << " for thread object " << this << endl; cannam@62: #endif cannam@62: WaitForSingleObject(m_id, INFINITE); cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Waited on thread " << m_id << " for thread object " << this << endl; cannam@62: #endif cannam@62: m_extant = false; cannam@62: } cannam@62: } cannam@62: cannam@62: Thread::Id cannam@62: Thread::id() cannam@62: { cannam@62: return m_id; cannam@62: } cannam@62: cannam@62: bool cannam@62: Thread::threadingAvailable() cannam@62: { cannam@62: return true; cannam@62: } cannam@62: cannam@62: DWORD cannam@62: Thread::staticRun(LPVOID arg) cannam@62: { cannam@62: Thread *thread = static_cast(arg); cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: " << (void *)GetCurrentThreadId() << ": Running thread " << thread->m_id << " for thread object " << thread << endl; cannam@62: #endif cannam@62: thread->run(); cannam@62: return 0; cannam@62: } cannam@62: cannam@62: Mutex::Mutex() cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: : cannam@62: m_lockedBy(-1) cannam@62: #endif cannam@62: { cannam@62: m_mutex = CreateMutex(NULL, FALSE, NULL); cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: Mutex::~Mutex() cannam@62: { cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: CloseHandle(m_mutex); cannam@62: } cannam@62: cannam@62: void cannam@62: Mutex::lock() cannam@62: { cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: DWORD tid = GetCurrentThreadId(); cannam@62: if (m_lockedBy == tid) { cannam@62: cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; cannam@62: } cannam@62: #endif cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: WaitForSingleObject(m_mutex, INFINITE); cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: m_lockedBy = tid; cannam@62: #endif cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: void cannam@62: Mutex::unlock() cannam@62: { cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: DWORD tid = GetCurrentThreadId(); cannam@62: if (m_lockedBy != tid) { cannam@62: cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; cannam@62: return; cannam@62: } cannam@62: #endif cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: m_lockedBy = -1; cannam@62: #endif cannam@62: ReleaseMutex(m_mutex); cannam@62: } cannam@62: cannam@62: bool cannam@62: Mutex::trylock() cannam@62: { cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: DWORD tid = GetCurrentThreadId(); cannam@62: #endif cannam@62: DWORD result = WaitForSingleObject(m_mutex, 0); cannam@62: if (result == WAIT_TIMEOUT || result == WAIT_FAILED) { cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; cannam@62: #endif cannam@62: return false; cannam@62: } else { cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: m_lockedBy = tid; cannam@62: #endif cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; cannam@62: #endif cannam@62: return true; cannam@62: } cannam@62: } cannam@62: cannam@62: Condition::Condition(string name) : cannam@62: m_locked(false) cannam@62: #ifdef DEBUG_CONDITION cannam@62: , m_name(name) cannam@62: #endif cannam@62: { cannam@62: m_mutex = CreateMutex(NULL, FALSE, NULL); cannam@62: m_condition = CreateEvent(NULL, FALSE, FALSE, NULL); cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised condition " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: Condition::~Condition() cannam@62: { cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying condition " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: if (m_locked) ReleaseMutex(m_mutex); cannam@62: CloseHandle(m_condition); cannam@62: CloseHandle(m_mutex); cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::lock() cannam@62: { cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Want to lock " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: WaitForSingleObject(m_mutex, INFINITE); cannam@62: m_locked = true; cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Locked " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::unlock() cannam@62: { cannam@62: if (!m_locked) { cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Not locked " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: return; cannam@62: } cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Unlocking " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: m_locked = false; cannam@62: ReleaseMutex(m_mutex); cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::wait(int us) cannam@62: { cannam@62: if (us == 0) { cannam@62: cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Waiting on " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: SignalObjectAndWait(m_mutex, m_condition, INFINITE, FALSE); cannam@62: WaitForSingleObject(m_mutex, INFINITE); cannam@62: cannam@62: } else { cannam@62: cannam@62: DWORD ms = us / 1000; cannam@62: if (us > 0 && ms == 0) ms = 1; cannam@62: cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Timed waiting on " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: SignalObjectAndWait(m_mutex, m_condition, ms, FALSE); cannam@62: WaitForSingleObject(m_mutex, INFINITE); cannam@62: } cannam@62: cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Wait done on " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@71: cannam@71: m_locked = true; cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::signal() cannam@62: { cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)GetCurrentThreadId() << ": Signalling " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: SetEvent(m_condition); cannam@62: } cannam@62: cannam@62: #else /* !_WIN32 */ cannam@62: cannam@62: #ifdef USE_PTHREADS cannam@62: cannam@62: Thread::Thread() : cannam@62: m_id(0), cannam@62: m_extant(false) cannam@62: { cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Created thread object " << this << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: Thread::~Thread() cannam@62: { cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Destroying thread object " << this << ", id " << m_id << endl; cannam@62: #endif cannam@62: if (m_extant) { cannam@62: pthread_join(m_id, 0); cannam@62: } cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Destroyed thread object " << this << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: void cannam@62: Thread::start() cannam@62: { cannam@62: if (pthread_create(&m_id, 0, staticRun, this)) { cannam@62: cerr << "ERROR: thread creation failed" << endl; cannam@62: exit(1); cannam@62: } else { cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Created thread " << m_id << " for thread object " << this << endl; cannam@62: #endif cannam@62: m_extant = true; cannam@62: } cannam@62: } cannam@62: cannam@62: void cannam@62: Thread::wait() cannam@62: { cannam@62: if (m_extant) { cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Waiting on thread " << m_id << " for thread object " << this << endl; cannam@62: #endif cannam@62: pthread_join(m_id, 0); cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: Waited on thread " << m_id << " for thread object " << this << endl; cannam@62: #endif cannam@62: m_extant = false; cannam@62: } cannam@62: } cannam@62: cannam@62: Thread::Id cannam@62: Thread::id() cannam@62: { cannam@62: return m_id; cannam@62: } cannam@62: cannam@62: bool cannam@62: Thread::threadingAvailable() cannam@62: { cannam@62: return true; cannam@62: } cannam@62: cannam@62: void * cannam@62: Thread::staticRun(void *arg) cannam@62: { cannam@62: Thread *thread = static_cast(arg); cannam@62: #ifdef DEBUG_THREAD cannam@62: cerr << "THREAD DEBUG: " << (void *)pthread_self() << ": Running thread " << thread->m_id << " for thread object " << thread << endl; cannam@62: #endif cannam@62: thread->run(); cannam@62: return 0; cannam@62: } cannam@62: cannam@62: Mutex::Mutex() cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: : cannam@62: m_lockedBy(0), cannam@62: m_locked(false) cannam@62: #endif cannam@62: { cannam@62: pthread_mutex_init(&m_mutex, 0); cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Initialised mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: Mutex::~Mutex() cannam@62: { cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Destroying mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: pthread_mutex_destroy(&m_mutex); cannam@62: } cannam@62: cannam@62: void cannam@62: Mutex::lock() cannam@62: { cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: pthread_t tid = pthread_self(); cannam@62: if (m_locked && m_lockedBy == tid) { cannam@62: cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; cannam@62: } cannam@62: #endif cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: pthread_mutex_lock(&m_mutex); cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: m_lockedBy = tid; cannam@62: m_locked = true; cannam@62: #endif cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: void cannam@62: Mutex::unlock() cannam@62: { cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: pthread_t tid = pthread_self(); cannam@62: if (!m_locked) { cannam@62: cerr << "ERROR: Mutex " << &m_mutex << " not locked in unlock" << endl; cannam@62: return; cannam@62: } else if (m_lockedBy != tid) { cannam@62: cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; cannam@62: return; cannam@62: } cannam@62: #endif cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; cannam@62: #endif cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: m_locked = false; cannam@62: #endif cannam@62: pthread_mutex_unlock(&m_mutex); cannam@62: } cannam@62: cannam@62: bool cannam@62: Mutex::trylock() cannam@62: { cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: pthread_t tid = pthread_self(); cannam@62: #endif cannam@62: if (pthread_mutex_trylock(&m_mutex)) { cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; cannam@62: #endif cannam@62: return false; cannam@62: } else { cannam@62: #ifndef NO_THREAD_CHECKS cannam@62: m_lockedBy = tid; cannam@62: m_locked = true; cannam@62: #endif cannam@62: #ifdef DEBUG_MUTEX cannam@62: cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; cannam@62: #endif cannam@62: return true; cannam@62: } cannam@62: } cannam@62: Chris@189: Condition::Condition(string Chris@189: #ifdef DEBUG_CONDITION Chris@189: name Chris@189: #endif Chris@189: ) : cannam@62: m_locked(false) cannam@62: #ifdef DEBUG_CONDITION cannam@62: , m_name(name) cannam@62: #endif cannam@62: { cannam@62: pthread_mutex_init(&m_mutex, 0); cannam@62: pthread_cond_init(&m_condition, 0); cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Initialised condition " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: Condition::~Condition() cannam@62: { cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Destroying condition " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: if (m_locked) pthread_mutex_unlock(&m_mutex); cannam@62: pthread_cond_destroy(&m_condition); cannam@62: pthread_mutex_destroy(&m_mutex); cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::lock() cannam@62: { cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Want to lock " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: pthread_mutex_lock(&m_mutex); cannam@62: m_locked = true; cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Locked " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::unlock() cannam@62: { cannam@62: if (!m_locked) { cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Not locked " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: return; cannam@62: } cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Unlocking " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: m_locked = false; cannam@62: pthread_mutex_unlock(&m_mutex); cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::wait(int us) cannam@62: { cannam@62: if (us == 0) { cannam@62: cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Waiting on " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: pthread_cond_wait(&m_condition, &m_mutex); cannam@62: cannam@62: } else { cannam@62: cannam@62: struct timeval now; cannam@62: gettimeofday(&now, 0); cannam@62: cannam@62: now.tv_usec += us; cannam@62: while (now.tv_usec > 1000000) { cannam@62: now.tv_usec -= 1000000; cannam@62: ++now.tv_sec; cannam@62: } cannam@62: cannam@62: struct timespec timeout; cannam@62: timeout.tv_sec = now.tv_sec; cannam@62: timeout.tv_nsec = now.tv_usec * 1000; cannam@62: cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Timed waiting on " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: pthread_cond_timedwait(&m_condition, &m_mutex, &timeout); cannam@62: } cannam@62: cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Wait done on " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@69: cannam@69: m_locked = true; cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::signal() cannam@62: { cannam@62: #ifdef DEBUG_CONDITION cannam@62: cerr << "CONDITION DEBUG: " << (void *)pthread_self() << ": Signalling " << &m_condition << " \"" << m_name << "\"" << endl; cannam@62: #endif cannam@62: pthread_cond_signal(&m_condition); cannam@62: } cannam@62: cannam@62: #else /* !USE_PTHREADS */ cannam@62: cannam@62: Thread::Thread() cannam@62: { cannam@62: } cannam@62: cannam@62: Thread::~Thread() cannam@62: { cannam@62: } cannam@62: cannam@62: void cannam@62: Thread::start() cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: void cannam@62: Thread::wait() cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: Thread::Id cannam@62: Thread::id() cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: bool cannam@62: Thread::threadingAvailable() cannam@62: { cannam@62: return false; cannam@62: } cannam@62: cannam@62: Mutex::Mutex() cannam@62: { cannam@62: } cannam@62: cannam@62: Mutex::~Mutex() cannam@62: { cannam@62: } cannam@62: cannam@62: void cannam@62: Mutex::lock() cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: void cannam@62: Mutex::unlock() cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: bool cannam@62: Mutex::trylock() cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: Condition::Condition(const char *) cannam@62: { cannam@62: } cannam@62: cannam@62: Condition::~Condition() cannam@62: { cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::lock() cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::wait(int us) cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: void cannam@62: Condition::signal() cannam@62: { cannam@62: abort(); cannam@62: } cannam@62: cannam@62: #endif /* !USE_PTHREADS */ cannam@62: #endif /* !_WIN32 */ cannam@62: cannam@62: MutexLocker::MutexLocker(Mutex *mutex) : cannam@62: m_mutex(mutex) cannam@62: { cannam@62: if (m_mutex) { cannam@62: m_mutex->lock(); cannam@62: } cannam@62: } cannam@62: cannam@62: MutexLocker::~MutexLocker() cannam@62: { cannam@62: if (m_mutex) { cannam@62: m_mutex->unlock(); cannam@62: } cannam@62: } cannam@62: