xpcom/glue/Mutex.h

branch
TOR_BUG_9701
changeset 8
97036ab72558
equal deleted inserted replaced
-1:000000000000 0:d92a789aacc9
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 * vim: sw=4 ts=4 et :
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7 #ifndef mozilla_Mutex_h
8 #define mozilla_Mutex_h
9
10 #include "prlock.h"
11
12 #include "mozilla/BlockingResourceBase.h"
13 #include "mozilla/GuardObjects.h"
14
15 //
16 // Provides:
17 //
18 // - Mutex, a non-recursive mutex
19 // - MutexAutoLock, an RAII class for ensuring that Mutexes are properly
20 // locked and unlocked
21 // - MutexAutoUnlock, complementary sibling to MutexAutoLock
22 //
23 // - OffTheBooksMutex, a non-recursive mutex that doesn't do leak checking
24 // - OffTheBooksMutexAuto{Lock,Unlock} - Like MutexAuto{Lock,Unlock}, but for
25 // an OffTheBooksMutex.
26 //
27 // Using MutexAutoLock/MutexAutoUnlock etc. is MUCH preferred to making bare
28 // calls to Lock and Unlock.
29 //
30 namespace mozilla {
31
32 /**
33 * OffTheBooksMutex is identical to Mutex, except that OffTheBooksMutex doesn't
34 * include leak checking. Sometimes you want to intentionally "leak" a mutex
35 * until shutdown; in these cases, OffTheBooksMutex is for you.
36 */
37 class NS_COM_GLUE OffTheBooksMutex : BlockingResourceBase
38 {
39 public:
40 /**
41 * @param name A name which can reference this lock
42 * @returns If failure, nullptr
43 * If success, a valid Mutex* which must be destroyed
44 * by Mutex::DestroyMutex()
45 **/
46 OffTheBooksMutex(const char* name) :
47 BlockingResourceBase(name, eMutex)
48 {
49 mLock = PR_NewLock();
50 if (!mLock)
51 NS_RUNTIMEABORT("Can't allocate mozilla::Mutex");
52 }
53
54 ~OffTheBooksMutex()
55 {
56 NS_ASSERTION(mLock,
57 "improperly constructed Lock or double free");
58 // NSPR does consistency checks for us
59 PR_DestroyLock(mLock);
60 mLock = 0;
61 }
62
63 #ifndef DEBUG
64 /**
65 * Lock
66 * @see prlock.h
67 **/
68 void Lock()
69 {
70 PR_Lock(mLock);
71 }
72
73 /**
74 * Unlock
75 * @see prlock.h
76 **/
77 void Unlock()
78 {
79 PR_Unlock(mLock);
80 }
81
82 /**
83 * AssertCurrentThreadOwns
84 * @see prlock.h
85 **/
86 void AssertCurrentThreadOwns () const
87 {
88 }
89
90 /**
91 * AssertNotCurrentThreadOwns
92 * @see prlock.h
93 **/
94 void AssertNotCurrentThreadOwns () const
95 {
96 }
97
98 #else
99 void Lock();
100 void Unlock();
101
102 void AssertCurrentThreadOwns () const
103 {
104 PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(mLock);
105 }
106
107 void AssertNotCurrentThreadOwns () const
108 {
109 // FIXME bug 476536
110 }
111
112 #endif // ifndef DEBUG
113
114 private:
115 OffTheBooksMutex();
116 OffTheBooksMutex(const OffTheBooksMutex&);
117 OffTheBooksMutex& operator=(const OffTheBooksMutex&);
118
119 PRLock* mLock;
120
121 friend class CondVar;
122 };
123
124 /**
125 * Mutex
126 * When possible, use MutexAutoLock/MutexAutoUnlock to lock/unlock this
127 * mutex within a scope, instead of calling Lock/Unlock directly.
128 */
129 class NS_COM_GLUE Mutex : public OffTheBooksMutex
130 {
131 public:
132 Mutex(const char* name)
133 : OffTheBooksMutex(name)
134 {
135 MOZ_COUNT_CTOR(Mutex);
136 }
137
138 ~Mutex()
139 {
140 MOZ_COUNT_DTOR(Mutex);
141 }
142
143 private:
144 Mutex();
145 Mutex(const Mutex&);
146 Mutex& operator=(const Mutex&);
147 };
148
149 /**
150 * MutexAutoLock
151 * Acquires the Mutex when it enters scope, and releases it when it leaves
152 * scope.
153 *
154 * MUCH PREFERRED to bare calls to Mutex.Lock and Unlock.
155 */
156 template<typename T>
157 class NS_COM_GLUE MOZ_STACK_CLASS BaseAutoLock
158 {
159 public:
160 /**
161 * Constructor
162 * The constructor aquires the given lock. The destructor
163 * releases the lock.
164 *
165 * @param aLock A valid mozilla::Mutex* returned by
166 * mozilla::Mutex::NewMutex.
167 **/
168 BaseAutoLock(T& aLock MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
169 mLock(&aLock)
170 {
171 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
172 NS_ASSERTION(mLock, "null mutex");
173 mLock->Lock();
174 }
175
176 ~BaseAutoLock(void) {
177 mLock->Unlock();
178 }
179
180 private:
181 BaseAutoLock();
182 BaseAutoLock(BaseAutoLock&);
183 BaseAutoLock& operator=(BaseAutoLock&);
184 static void* operator new(size_t) CPP_THROW_NEW;
185 static void operator delete(void*);
186
187 T* mLock;
188 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
189 };
190
191 typedef BaseAutoLock<Mutex> MutexAutoLock;
192 typedef BaseAutoLock<OffTheBooksMutex> OffTheBooksMutexAutoLock;
193
194 /**
195 * MutexAutoUnlock
196 * Releases the Mutex when it enters scope, and re-acquires it when it leaves
197 * scope.
198 *
199 * MUCH PREFERRED to bare calls to Mutex.Unlock and Lock.
200 */
201 template<typename T>
202 class NS_COM_GLUE MOZ_STACK_CLASS BaseAutoUnlock
203 {
204 public:
205 BaseAutoUnlock(T& aLock MOZ_GUARD_OBJECT_NOTIFIER_PARAM) :
206 mLock(&aLock)
207 {
208 MOZ_GUARD_OBJECT_NOTIFIER_INIT;
209 NS_ASSERTION(mLock, "null lock");
210 mLock->Unlock();
211 }
212
213 ~BaseAutoUnlock()
214 {
215 mLock->Lock();
216 }
217
218 private:
219 BaseAutoUnlock();
220 BaseAutoUnlock(BaseAutoUnlock&);
221 BaseAutoUnlock& operator =(BaseAutoUnlock&);
222 static void* operator new(size_t) CPP_THROW_NEW;
223 static void operator delete(void*);
224
225 T* mLock;
226 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
227 };
228
229 typedef BaseAutoUnlock<Mutex> MutexAutoUnlock;
230 typedef BaseAutoUnlock<OffTheBooksMutex> OffTheBooksMutexAutoUnlock;
231
232 } // namespace mozilla
233
234
235 #endif // ifndef mozilla_Mutex_h

mercurial