Home | History | Annotate | Download | only in source
      1 //===-- PThreadMutex.h ------------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 //  Created by Greg Clayton on 6/16/07.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef __PThreadMutex_h__
     15 #define __PThreadMutex_h__
     16 
     17 #include <pthread.h>
     18 #include <assert.h>
     19 #include <stdint.h>
     20 
     21 //#define DEBUG_PTHREAD_MUTEX_DEADLOCKS 1
     22 
     23 #if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
     24 #define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex, __FUNCTION__, __FILE__, __LINE__)
     25 
     26 #else
     27 #define PTHREAD_MUTEX_LOCKER(var, mutex) PThreadMutex::Locker var(mutex)
     28 #endif
     29 
     30 class PThreadMutex
     31 {
     32 public:
     33 
     34     class Locker
     35     {
     36     public:
     37 #if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
     38 
     39         Locker(PThreadMutex& m, const char *function, const char *file, int line);
     40         Locker(PThreadMutex* m, const char *function, const char *file, int line);
     41         Locker(pthread_mutex_t *mutex, const char *function, const char *file, int line);
     42         ~Locker();
     43         void Lock();
     44         void Unlock();
     45 
     46 #else
     47         Locker(PThreadMutex& m) :
     48             m_pMutex(m.Mutex())
     49         {
     50             Lock();
     51         }
     52 
     53         Locker(PThreadMutex* m) :
     54             m_pMutex(m ? m->Mutex() : NULL)
     55         {
     56             Lock();
     57         }
     58 
     59         Locker(pthread_mutex_t *mutex) :
     60             m_pMutex(mutex)
     61         {
     62             Lock();
     63         }
     64 
     65         void Lock()
     66         {
     67             if (m_pMutex)
     68                 ::pthread_mutex_lock (m_pMutex);
     69         }
     70 
     71         void Unlock()
     72         {
     73             if (m_pMutex)
     74                 ::pthread_mutex_unlock (m_pMutex);
     75         }
     76 
     77         ~Locker()
     78         {
     79             Unlock();
     80         }
     81 
     82 #endif
     83 
     84         // unlock any the current mutex and lock the new one if it is valid
     85         void Reset(pthread_mutex_t *pMutex = NULL)
     86         {
     87             Unlock();
     88             m_pMutex = pMutex;
     89             Lock();
     90         }
     91         pthread_mutex_t *m_pMutex;
     92 #if defined (DEBUG_PTHREAD_MUTEX_DEADLOCKS)
     93         const char *m_function;
     94         const char *m_file;
     95         int m_line;
     96         uint64_t m_lock_time;
     97 #endif
     98     };
     99 
    100 
    101     PThreadMutex()
    102     {
    103         int err;
    104         err = ::pthread_mutex_init (&m_mutex, NULL);        assert(err == 0);
    105     }
    106 
    107     PThreadMutex(int type)
    108     {
    109         int err;
    110         ::pthread_mutexattr_t attr;
    111         err = ::pthread_mutexattr_init (&attr);             assert(err == 0);
    112         err = ::pthread_mutexattr_settype (&attr, type);    assert(err == 0);
    113         err = ::pthread_mutex_init (&m_mutex, &attr);       assert(err == 0);
    114         err = ::pthread_mutexattr_destroy (&attr);          assert(err == 0);
    115     }
    116 
    117     ~PThreadMutex()
    118     {
    119         int err;
    120         err = ::pthread_mutex_destroy (&m_mutex);
    121         if (err != 0)
    122         {
    123             err = Unlock();
    124             if (err == 0)
    125                 ::pthread_mutex_destroy (&m_mutex);
    126         }
    127     }
    128 
    129     pthread_mutex_t *Mutex()
    130     {
    131         return &m_mutex;
    132     }
    133 
    134     int Lock()
    135     {
    136         return ::pthread_mutex_lock (&m_mutex);
    137     }
    138 
    139     int Unlock()
    140     {
    141         return ::pthread_mutex_unlock (&m_mutex);
    142     }
    143 
    144 protected:
    145     pthread_mutex_t        m_mutex;
    146 };
    147 
    148 #endif
    149