|  | //===-- PThreadMutex.h ------------------------------------------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | //  Created by Greg Clayton on 6/16/07. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef __PThreadMutex_h__ | 
|  | #define __PThreadMutex_h__ | 
|  |  | 
|  | #include <pthread.h> | 
|  | #include <assert.h> | 
|  | #include <stdint.h> | 
|  |  | 
|  | //#define DEBUG_PTHREAD_MUTEX_DEADLOCKS 1 | 
|  |  | 
|  | #if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS) | 
|  | #define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__) | 
|  |  | 
|  | #else | 
|  | #define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex) | 
|  | #endif | 
|  |  | 
|  | class PThreadMutex | 
|  | { | 
|  | public: | 
|  |  | 
|  | class Locker | 
|  | { | 
|  | public: | 
|  | #if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS) | 
|  |  | 
|  | Locker(PThreadMutex& m, const char *function, const char *file, int line); | 
|  | Locker(PThreadMutex* m, const char *function, const char *file, int line); | 
|  | Locker(pthread_mutex_t *mutex, const char *function, const char *file, int line); | 
|  | ~Locker(); | 
|  | void Lock(); | 
|  | void Unlock(); | 
|  |  | 
|  | #else | 
|  | Locker(PThreadMutex& m) : | 
|  | m_pMutex(m.Mutex()) | 
|  | { | 
|  | Lock(); | 
|  | } | 
|  |  | 
|  | Locker(PThreadMutex* m) : | 
|  | m_pMutex(m ? m->Mutex() : NULL) | 
|  | { | 
|  | Lock(); | 
|  | } | 
|  |  | 
|  | Locker(pthread_mutex_t *mutex) : | 
|  | m_pMutex(mutex) | 
|  | { | 
|  | Lock(); | 
|  | } | 
|  |  | 
|  | void Lock() | 
|  | { | 
|  | if (m_pMutex) | 
|  | ::pthread_mutex_lock (m_pMutex); | 
|  | } | 
|  |  | 
|  | void Unlock() | 
|  | { | 
|  | if (m_pMutex) | 
|  | ::pthread_mutex_unlock (m_pMutex); | 
|  | } | 
|  |  | 
|  | ~Locker() | 
|  | { | 
|  | Unlock(); | 
|  | } | 
|  |  | 
|  | #endif | 
|  |  | 
|  | // unlock any the current mutex and lock the new one if it is valid | 
|  | void Reset(pthread_mutex_t *pMutex = NULL) | 
|  | { | 
|  | Unlock(); | 
|  | m_pMutex = pMutex; | 
|  | Lock(); | 
|  | } | 
|  | pthread_mutex_t *m_pMutex; | 
|  | #if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS) | 
|  | const char *m_function; | 
|  | const char *m_file; | 
|  | int m_line; | 
|  | uint64_t m_lock_time; | 
|  | #endif | 
|  | }; | 
|  |  | 
|  |  | 
|  | PThreadMutex() | 
|  | { | 
|  | int err; | 
|  | err = ::pthread_mutex_init (&m_mutex, NULL);        assert(err == 0); | 
|  | } | 
|  |  | 
|  | PThreadMutex(int type) | 
|  | { | 
|  | int err; | 
|  | ::pthread_mutexattr_t attr; | 
|  | err = ::pthread_mutexattr_init (&attr);             assert(err == 0); | 
|  | err = ::pthread_mutexattr_settype (&attr, type);    assert(err == 0); | 
|  | err = ::pthread_mutex_init (&m_mutex, &attr);       assert(err == 0); | 
|  | err = ::pthread_mutexattr_destroy (&attr);          assert(err == 0); | 
|  | } | 
|  |  | 
|  | ~PThreadMutex() | 
|  | { | 
|  | int err; | 
|  | err = ::pthread_mutex_destroy (&m_mutex); | 
|  | if (err != 0) | 
|  | { | 
|  | err = Unlock(); | 
|  | if (err == 0) | 
|  | ::pthread_mutex_destroy (&m_mutex); | 
|  | } | 
|  | } | 
|  |  | 
|  | pthread_mutex_t *Mutex() | 
|  | { | 
|  | return &m_mutex; | 
|  | } | 
|  |  | 
|  | int Lock() | 
|  | { | 
|  | return ::pthread_mutex_lock (&m_mutex); | 
|  | } | 
|  |  | 
|  | int Unlock() | 
|  | { | 
|  | return ::pthread_mutex_unlock (&m_mutex); | 
|  | } | 
|  |  | 
|  | protected: | 
|  | pthread_mutex_t        m_mutex; | 
|  | }; | 
|  |  | 
|  | #endif |