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 
PThreadMutex()101     PThreadMutex()
102     {
103         int err;
104         err = ::pthread_mutex_init (&m_mutex, NULL);        assert(err == 0);
105     }
106 
PThreadMutex(int type)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 
~PThreadMutex()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 
Mutex()129     pthread_mutex_t *Mutex()
130     {
131         return &m_mutex;
132     }
133 
Lock()134     int Lock()
135     {
136         return ::pthread_mutex_lock (&m_mutex);
137     }
138 
Unlock()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