PThreadMutex.h revision 24943d2ee8bfaa7cf5893e4709143924157a5c1e
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
30class PThreadMutex
31{
32public:
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
144protected:
145    pthread_mutex_t        m_mutex;
146};
147
148#endif
149