|
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 |