Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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/. */
7 #ifndef mozilla_Mutex_h
8 #define mozilla_Mutex_h
10 #include "prlock.h"
12 #include "mozilla/BlockingResourceBase.h"
13 #include "mozilla/GuardObjects.h"
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 {
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 }
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 }
63 #ifndef DEBUG
64 /**
65 * Lock
66 * @see prlock.h
67 **/
68 void Lock()
69 {
70 PR_Lock(mLock);
71 }
73 /**
74 * Unlock
75 * @see prlock.h
76 **/
77 void Unlock()
78 {
79 PR_Unlock(mLock);
80 }
82 /**
83 * AssertCurrentThreadOwns
84 * @see prlock.h
85 **/
86 void AssertCurrentThreadOwns () const
87 {
88 }
90 /**
91 * AssertNotCurrentThreadOwns
92 * @see prlock.h
93 **/
94 void AssertNotCurrentThreadOwns () const
95 {
96 }
98 #else
99 void Lock();
100 void Unlock();
102 void AssertCurrentThreadOwns () const
103 {
104 PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(mLock);
105 }
107 void AssertNotCurrentThreadOwns () const
108 {
109 // FIXME bug 476536
110 }
112 #endif // ifndef DEBUG
114 private:
115 OffTheBooksMutex();
116 OffTheBooksMutex(const OffTheBooksMutex&);
117 OffTheBooksMutex& operator=(const OffTheBooksMutex&);
119 PRLock* mLock;
121 friend class CondVar;
122 };
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 }
138 ~Mutex()
139 {
140 MOZ_COUNT_DTOR(Mutex);
141 }
143 private:
144 Mutex();
145 Mutex(const Mutex&);
146 Mutex& operator=(const Mutex&);
147 };
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 }
176 ~BaseAutoLock(void) {
177 mLock->Unlock();
178 }
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*);
187 T* mLock;
188 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
189 };
191 typedef BaseAutoLock<Mutex> MutexAutoLock;
192 typedef BaseAutoLock<OffTheBooksMutex> OffTheBooksMutexAutoLock;
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 }
213 ~BaseAutoUnlock()
214 {
215 mLock->Lock();
216 }
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*);
225 T* mLock;
226 MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
227 };
229 typedef BaseAutoUnlock<Mutex> MutexAutoUnlock;
230 typedef BaseAutoUnlock<OffTheBooksMutex> OffTheBooksMutexAutoUnlock;
232 } // namespace mozilla
235 #endif // ifndef mozilla_Mutex_h