VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h@ 62330

Last change on this file since 62330 was 62330, checked in by vboxsync, 8 years ago

xpcom: for nsAutoLock and friends don't provide fake implementations
for default and copy constructors, and operators =, new and delete.
Constify reference arguments where applicable.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.6 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38
39/*
40 A stack-based lock object that makes using PRLock a bit more
41 convenient. It acquires the monitor when constructed, and releases
42 it when it goes out of scope.
43
44 For example,
45
46 class Foo {
47 private:
48 PRLock* mLock;
49
50 public:
51 Foo(void) {
52 mLock = PR_NewLock();
53 }
54
55 ~Foo(void) {
56 PR_DestroyLock(mLock);
57 }
58
59 void ThreadSafeMethod(void) {
60 // we're don't hold the lock yet...
61
62 nsAutoLock lock(mLock);
63 // ...but now we do.
64
65 // we even can do wacky stuff like return from arbitrary places w/o
66 // worrying about forgetting to release the lock
67 if (some_weird_condition)
68 return;
69
70 // otherwise do some other stuff
71 }
72
73 void ThreadSafeBlockScope(void) {
74 // we're not in the lock here...
75
76 {
77 nsAutoLock lock(mLock);
78 // but we are now, at least until the block scope closes
79 }
80
81 // ...now we're not in the lock anymore
82 }
83 };
84
85 A similar stack-based locking object is available for PRMonitor. The
86 major difference is that the PRMonitor must be created and destroyed
87 via the static methods on nsAutoMonitor.
88
89 For example:
90 Foo::Foo() {
91 mMon = nsAutoMonitor::NewMonitor("FooMonitor");
92 }
93 nsresult Foo::MyMethod(...) {
94 nsAutoMonitor mon(mMon);
95 ...
96 // go ahead and do deeply nested returns...
97 return NS_ERROR_FAILURE;
98 ...
99 // or call Wait or Notify...
100 mon.Wait();
101 ...
102 // cleanup is automatic
103 }
104 */
105
106#ifndef nsAutoLock_h__
107#define nsAutoLock_h__
108
109#include "nscore.h"
110#include "prlock.h"
111#include "prlog.h"
112
113/**
114 * nsAutoLockBase
115 * This is the base class for the stack-based locking objects.
116 * Clients of derived classes need not play with this superclass.
117 **/
118class NS_COM nsAutoLockBase {
119protected:
120 nsAutoLockBase() {}
121 enum nsAutoLockType {eAutoLock, eAutoMonitor, eAutoCMonitor};
122
123#ifdef DEBUG
124 nsAutoLockBase(void* addr, nsAutoLockType type);
125 ~nsAutoLockBase();
126
127 void Show();
128 void Hide();
129
130 void* mAddr;
131 nsAutoLockBase* mDown;
132 nsAutoLockType mType;
133#else
134 nsAutoLockBase(void* addr, nsAutoLockType type) {}
135 ~nsAutoLockBase() {}
136
137 void Show() {}
138 void Hide() {}
139#endif
140};
141
142/**
143 * nsAutoLock
144 * Stack-based locking object for PRLock.
145 **/
146class NS_COM nsAutoLock : public nsAutoLockBase {
147private:
148 PRLock* mLock;
149 PRBool mLocked;
150
151 // Not meant to be implemented. This makes it a compiler error to
152 // construct or assign an nsAutoLock object incorrectly.
153 nsAutoLock(void);
154 nsAutoLock(const nsAutoLock& /*aLock*/);
155 nsAutoLock& operator =(const nsAutoLock& /*aLock*/);
156
157 // Not meant to be implemented. This makes it a compiler error to
158 // attempt to create an nsAutoLock object on the heap.
159 static void* operator new(size_t /*size*/) CPP_THROW_NEW;
160 static void operator delete(void* /*memory*/);
161
162public:
163 /**
164 * Constructor
165 * The constructor aquires the given lock. The destructor
166 * releases the lock.
167 *
168 * @param aLock A valid PRLock* returned from the NSPR's
169 * PR_NewLock() function.
170 **/
171 nsAutoLock(PRLock* aLock)
172 : nsAutoLockBase(aLock, eAutoLock),
173 mLock(aLock),
174 mLocked(PR_TRUE) {
175 PR_ASSERT(mLock);
176
177 // This will assert deep in the bowels of NSPR if you attempt
178 // to re-enter the lock.
179 PR_Lock(mLock);
180 }
181
182 ~nsAutoLock(void) {
183 if (mLocked)
184 PR_Unlock(mLock);
185 }
186
187 /**
188 * lock
189 * Client may call this to reaquire the given lock. Take special
190 * note that attempting to aquire a locked lock will hang or crash.
191 **/
192 void lock() {
193 Show();
194 PR_ASSERT(!mLocked);
195 PR_Lock(mLock);
196 mLocked = PR_TRUE;
197 }
198
199
200 /**
201 * unlock
202 * Client may call this to release the given lock. Take special
203 * note unlocking an unlocked lock has undefined results.
204 **/
205 void unlock() {
206 PR_ASSERT(mLocked);
207 PR_Unlock(mLock);
208 mLocked = PR_FALSE;
209 Hide();
210 }
211};
212
213#include "prcmon.h"
214#include "nsError.h"
215#include "nsDebug.h"
216
217class NS_COM nsAutoMonitor : public nsAutoLockBase {
218public:
219
220 /**
221 * NewMonitor
222 * Allocates a new PRMonitor for use with nsAutoMonitor.
223 * @param name A (unique /be?) name which can reference this monitor
224 * @returns nsnull if failure
225 * A valid PRMonitor* is successful while must be destroyed
226 * by nsAutoMonitor::DestroyMonitor()
227 **/
228 static PRMonitor* NewMonitor(const char* name);
229 static void DestroyMonitor(PRMonitor* mon);
230
231
232 /**
233 * Constructor
234 * The constructor locks the given monitor. During destruction
235 * the monitor will be unlocked.
236 *
237 * @param mon A valid PRMonitor* returned from
238 * nsAutoMonitor::NewMonitor().
239 **/
240 nsAutoMonitor(PRMonitor* mon)
241 : nsAutoLockBase((void*)mon, eAutoMonitor),
242 mMonitor(mon), mLockCount(0)
243 {
244 NS_ASSERTION(mMonitor, "null monitor");
245 if (mMonitor) {
246 PR_EnterMonitor(mMonitor);
247 mLockCount = 1;
248 }
249 }
250
251 ~nsAutoMonitor() {
252 NS_ASSERTION(mMonitor, "null monitor");
253 if (mMonitor && mLockCount) {
254#ifdef DEBUG
255 PRStatus status =
256#endif
257 PR_ExitMonitor(mMonitor);
258 NS_ASSERTION(status == PR_SUCCESS, "PR_ExitMonitor failed");
259 }
260 }
261
262 /**
263 * Enter
264 * Client may call this to reenter the given monitor.
265 * @see prmon.h
266 **/
267 void Enter();
268
269 /**
270 * Exit
271 * Client may call this to exit the given monitor.
272 * @see prmon.h
273 **/
274 void Exit();
275
276 /**
277 * Wait
278 * @see prmon.h
279 **/
280 nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
281 return PR_Wait(mMonitor, interval) == PR_SUCCESS
282 ? NS_OK : NS_ERROR_FAILURE;
283 }
284
285 /**
286 * Notify
287 * @see prmon.h
288 **/
289 nsresult Notify() {
290 return PR_Notify(mMonitor) == PR_SUCCESS
291 ? NS_OK : NS_ERROR_FAILURE;
292 }
293
294 /**
295 * NotifyAll
296 * @see prmon.h
297 **/
298 nsresult NotifyAll() {
299 return PR_NotifyAll(mMonitor) == PR_SUCCESS
300 ? NS_OK : NS_ERROR_FAILURE;
301 }
302
303private:
304 PRMonitor* mMonitor;
305 PRInt32 mLockCount;
306
307 // Not meant to be implemented. This makes it a compiler error to
308 // construct or assign an nsAutoLock object incorrectly.
309 nsAutoMonitor(void);
310 nsAutoMonitor(const nsAutoMonitor& /*aMon*/);
311 nsAutoMonitor& operator =(const nsAutoMonitor& /*aMon*/);
312
313 // Not meant to be implemented. This makes it a compiler error to
314 // attempt to create an nsAutoLock object on the heap.
315 static void* operator new(size_t /*size*/) CPP_THROW_NEW;
316 static void operator delete(void* /*memory*/);
317};
318
319////////////////////////////////////////////////////////////////////////////////
320// Once again, this time with a cache...
321// (Using this avoids the need to allocate a PRMonitor, which may be useful when
322// a large number of objects of the same class need associated monitors.)
323
324#include "prcmon.h"
325#include "nsError.h"
326
327class NS_COM nsAutoCMonitor : public nsAutoLockBase {
328public:
329 nsAutoCMonitor(void* lockObject)
330 : nsAutoLockBase(lockObject, eAutoCMonitor),
331 mLockObject(lockObject), mLockCount(0)
332 {
333 NS_ASSERTION(lockObject, "null lock object");
334 PR_CEnterMonitor(mLockObject);
335 mLockCount = 1;
336 }
337
338 ~nsAutoCMonitor() {
339 if (mLockCount) {
340#ifdef DEBUG
341 PRStatus status =
342#endif
343 PR_CExitMonitor(mLockObject);
344 NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
345 }
346 }
347
348 void Enter();
349 void Exit();
350
351 nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
352 return PR_CWait(mLockObject, interval) == PR_SUCCESS
353 ? NS_OK : NS_ERROR_FAILURE;
354 }
355
356 nsresult Notify() {
357 return PR_CNotify(mLockObject) == PR_SUCCESS
358 ? NS_OK : NS_ERROR_FAILURE;
359 }
360
361 nsresult NotifyAll() {
362 return PR_CNotifyAll(mLockObject) == PR_SUCCESS
363 ? NS_OK : NS_ERROR_FAILURE;
364 }
365
366private:
367 void* mLockObject;
368 PRInt32 mLockCount;
369
370 // Not meant to be implemented. This makes it a compiler error to
371 // construct or assign an nsAutoLock object incorrectly.
372 nsAutoCMonitor(void);
373 nsAutoCMonitor(const nsAutoCMonitor& /*aMon*/);
374 nsAutoCMonitor& operator =(const nsAutoCMonitor& /*aMon*/);
375
376 // Not meant to be implemented. This makes it a compiler error to
377 // attempt to create an nsAutoLock object on the heap.
378 static void* operator new(size_t /*size*/) CPP_THROW_NEW;
379 static void operator delete(void* /*memory*/);
380};
381
382#endif // nsAutoLock_h__
383
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette