Merge pull request #314 from ceph/wip-4228
[ceph.git] / src / common / Mutex.h
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- 
2 // vim: ts=8 sw=2 smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License version 2.1, as published by the Free Software 
11  * Foundation.  See file COPYING.
12  * 
13  */
14
15 #ifndef __MUTEX_H
16 #define __MUTEX_H
17
18 #include <pthread.h>
19 #include "include/assert.h"
20 #include "lockdep.h"
21
22 #define LOCKDEP
23
24
25 class Mutex {
26 private:
27   const char *name;
28   int id;
29   bool recursive;
30   bool lockdep;
31
32   pthread_mutex_t _m;
33   int nlock;
34
35   // don't allow copying.
36   void operator=(Mutex &M) {}
37   Mutex( const Mutex &M ) {}
38
39 #ifdef LOCKDEP
40   void _register() {
41     id = lockdep_register(name);
42   }
43   void _will_lock() { // about to lock
44     id = lockdep_will_lock(name, id);
45   }
46   void _locked() {    // just locked
47     id = lockdep_locked(name, id);
48   }
49   void _unlocked() {  // just unlocked
50     id = lockdep_unlocked(name, id);
51   }
52 #else
53   void _register() {}
54   void _will_lock() {} // about to lock
55   void _locked() {}    // just locked
56   void _unlocked() {}  // just unlocked
57 #endif
58
59 public:
60   Mutex(const char *n, bool r = false, bool ld=true) : name(n), id(-1), recursive(r), lockdep(ld), nlock(0) {
61     if (recursive) {
62       pthread_mutexattr_t attr;
63       pthread_mutexattr_init(&attr);
64       pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
65       pthread_mutex_init(&_m,&attr);
66       pthread_mutexattr_destroy(&attr);
67     } else {
68       pthread_mutex_init(&_m, NULL);
69     }
70     if (lockdep && g_lockdep) _register();
71   }
72   ~Mutex() {
73     assert(nlock == 0);
74     pthread_mutex_destroy(&_m); 
75   }
76
77   bool is_locked() {
78     return (nlock > 0);
79   }
80
81   bool TryLock() {
82     int r = pthread_mutex_trylock(&_m);
83     if (r == 0) {
84       if (lockdep && g_lockdep) _locked();
85       nlock++;
86     }
87     return r == 0;
88   }
89
90   void Lock() {
91     if (lockdep && g_lockdep) _will_lock();
92     int r = pthread_mutex_lock(&_m);
93     if (lockdep && g_lockdep) _locked();
94     assert(r == 0);
95     nlock++;
96   }
97
98   void Unlock() {
99     assert(nlock > 0);
100     --nlock;
101     int r = pthread_mutex_unlock(&_m);
102     assert(r == 0);
103     if (lockdep && g_lockdep) _unlocked();
104   }
105
106   friend class Cond;
107
108
109 public:
110   class Locker {
111     Mutex &mutex;
112
113   public:
114     Locker(Mutex& m) : mutex(m) {
115       mutex.Lock();
116     }
117     ~Locker() {
118       mutex.Unlock();
119     }
120   };
121 };
122
123
124 #endif