fazekasgy@37: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ fazekasgy@37: fazekasgy@37: /* fazekasgy@37: Basic cross-platform mutex abstraction class. fazekasgy@37: This file copyright 2007 Chris Cannam. fazekasgy@37: */ fazekasgy@37: fazekasgy@37: #include "Mutex.h" fazekasgy@37: #include fazekasgy@37: fazekasgy@37: #ifndef _WIN32 fazekasgy@37: #include fazekasgy@37: #include fazekasgy@37: #endif fazekasgy@37: fazekasgy@37: using std::cerr; fazekasgy@37: using std::endl; fazekasgy@37: using std::string; fazekasgy@37: fazekasgy@37: #ifdef _WIN32 fazekasgy@37: fazekasgy@37: Mutex::Mutex() fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: : fazekasgy@37: m_lockedBy(-1) fazekasgy@37: #endif fazekasgy@37: { fazekasgy@37: m_mutex = CreateMutex(NULL, FALSE, NULL); fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Initialised mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: } fazekasgy@37: fazekasgy@37: Mutex::~Mutex() fazekasgy@37: { fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)GetCurrentThreadId() << ": Destroying mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: CloseHandle(m_mutex); fazekasgy@37: } fazekasgy@37: fazekasgy@37: void fazekasgy@37: Mutex::lock() fazekasgy@37: { fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: DWORD tid = GetCurrentThreadId(); fazekasgy@37: if (m_lockedBy == tid) { fazekasgy@37: cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; fazekasgy@37: } fazekasgy@37: #endif fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: WaitForSingleObject(m_mutex, INFINITE); fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: m_lockedBy = tid; fazekasgy@37: #endif fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: } fazekasgy@37: fazekasgy@37: void fazekasgy@37: Mutex::unlock() fazekasgy@37: { fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: DWORD tid = GetCurrentThreadId(); fazekasgy@37: if (m_lockedBy != tid) { fazekasgy@37: cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; fazekasgy@37: return; fazekasgy@37: } fazekasgy@37: #endif fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: m_lockedBy = -1; fazekasgy@37: #endif fazekasgy@37: ReleaseMutex(m_mutex); fazekasgy@37: } fazekasgy@37: fazekasgy@37: bool fazekasgy@37: Mutex::trylock() fazekasgy@37: { fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: DWORD tid = GetCurrentThreadId(); fazekasgy@37: #endif fazekasgy@37: DWORD result = WaitForSingleObject(m_mutex, 0); fazekasgy@37: if (result == WAIT_TIMEOUT || result == WAIT_FAILED) { fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; fazekasgy@37: #endif fazekasgy@37: return false; fazekasgy@37: } else { fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: m_lockedBy = tid; fazekasgy@37: #endif fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; fazekasgy@37: #endif fazekasgy@37: return true; fazekasgy@37: } fazekasgy@37: } fazekasgy@37: fazekasgy@37: #else /* !_WIN32 */ fazekasgy@37: fazekasgy@37: Mutex::Mutex() fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: : fazekasgy@37: m_lockedBy(0), fazekasgy@37: m_locked(false) fazekasgy@37: #endif fazekasgy@37: { fazekasgy@37: pthread_mutex_init(&m_mutex, 0); fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Initialised mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: } fazekasgy@37: fazekasgy@37: Mutex::~Mutex() fazekasgy@37: { fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)pthread_self() << ": Destroying mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: pthread_mutex_destroy(&m_mutex); fazekasgy@37: } fazekasgy@37: fazekasgy@37: void fazekasgy@37: Mutex::lock() fazekasgy@37: { fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: pthread_t tid = pthread_self(); fazekasgy@37: if (m_locked && m_lockedBy == tid) { fazekasgy@37: cerr << "ERROR: Deadlock on mutex " << &m_mutex << endl; fazekasgy@37: } fazekasgy@37: #endif fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Want to lock mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: pthread_mutex_lock(&m_mutex); fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: m_lockedBy = tid; fazekasgy@37: m_locked = true; fazekasgy@37: #endif fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: } fazekasgy@37: fazekasgy@37: void fazekasgy@37: Mutex::unlock() fazekasgy@37: { fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: pthread_t tid = pthread_self(); fazekasgy@37: if (!m_locked) { fazekasgy@37: cerr << "ERROR: Mutex " << &m_mutex << " not locked in unlock" << endl; fazekasgy@37: return; fazekasgy@37: } else if (m_lockedBy != tid) { fazekasgy@37: cerr << "ERROR: Mutex " << &m_mutex << " not owned by unlocking thread" << endl; fazekasgy@37: return; fazekasgy@37: } fazekasgy@37: #endif fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Unlocking mutex " << &m_mutex << endl; fazekasgy@37: #endif fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: m_locked = false; fazekasgy@37: #endif fazekasgy@37: pthread_mutex_unlock(&m_mutex); fazekasgy@37: } fazekasgy@37: fazekasgy@37: bool fazekasgy@37: Mutex::trylock() fazekasgy@37: { fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: pthread_t tid = pthread_self(); fazekasgy@37: #endif fazekasgy@37: if (pthread_mutex_trylock(&m_mutex)) { fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Mutex " << &m_mutex << " unavailable" << endl; fazekasgy@37: #endif fazekasgy@37: return false; fazekasgy@37: } else { fazekasgy@37: #ifndef NO_THREAD_CHECKS fazekasgy@37: m_lockedBy = tid; fazekasgy@37: m_locked = true; fazekasgy@37: #endif fazekasgy@37: #ifdef DEBUG_MUTEX fazekasgy@37: cerr << "MUTEX DEBUG: " << (void *)tid << ": Locked mutex " << &m_mutex << " (from trylock)" << endl; fazekasgy@37: #endif fazekasgy@37: return true; fazekasgy@37: } fazekasgy@37: } fazekasgy@37: fazekasgy@37: #endif fazekasgy@37: fazekasgy@37: MutexLocker::MutexLocker(Mutex *mutex) : fazekasgy@37: m_mutex(mutex) fazekasgy@37: { fazekasgy@37: if (m_mutex) { fazekasgy@37: m_mutex->lock(); fazekasgy@37: } fazekasgy@37: } fazekasgy@37: fazekasgy@37: MutexLocker::~MutexLocker() fazekasgy@37: { fazekasgy@37: if (m_mutex) { fazekasgy@37: m_mutex->unlock(); fazekasgy@37: } fazekasgy@37: } fazekasgy@37: