VirtualBox

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

Last change on this file since 6542 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.8 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(nsAutoLock& /*aLock*/) {}
155 nsAutoLock& operator =(nsAutoLock& /*aLock*/) {
156 return *this;
157 }
158
159 // Not meant to be implemented. This makes it a compiler error to
160 // attempt to create an nsAutoLock object on the heap.
161 static void* operator new(size_t /*size*/) CPP_THROW_NEW {
162 return nsnull;
163 }
164 static void operator delete(void* /*memory*/) {}
165
166public:
167 /**
168 * Constructor
169 * The constructor aquires the given lock. The destructor
170 * releases the lock.
171 *
172 * @param aLock A valid PRLock* returned from the NSPR's
173 * PR_NewLock() function.
174 **/
175 nsAutoLock(PRLock* aLock)
176 : nsAutoLockBase(aLock, eAutoLock),
177 mLock(aLock),
178 mLocked(PR_TRUE) {
179 PR_ASSERT(mLock);
180
181 // This will assert deep in the bowels of NSPR if you attempt
182 // to re-enter the lock.
183 PR_Lock(mLock);
184 }
185
186 ~nsAutoLock(void) {
187 if (mLocked)
188 PR_Unlock(mLock);
189 }
190
191 /**
192 * lock
193 * Client may call this to reaquire the given lock. Take special
194 * note that attempting to aquire a locked lock will hang or crash.
195 **/
196 void lock() {
197 Show();
198 PR_ASSERT(!mLocked);
199 PR_Lock(mLock);
200 mLocked = PR_TRUE;
201 }
202
203
204 /**
205 * unlock
206 * Client may call this to release the given lock. Take special
207 * note unlocking an unlocked lock has undefined results.
208 **/
209 void unlock() {
210 PR_ASSERT(mLocked);
211 PR_Unlock(mLock);
212 mLocked = PR_FALSE;
213 Hide();
214 }
215};
216
217#include "prcmon.h"
218#include "nsError.h"
219#include "nsDebug.h"
220
221class NS_COM nsAutoMonitor : public nsAutoLockBase {
222public:
223
224 /**
225 * NewMonitor
226 * Allocates a new PRMonitor for use with nsAutoMonitor.
227 * @param name A (unique /be?) name which can reference this monitor
228 * @returns nsnull if failure
229 * A valid PRMonitor* is successful while must be destroyed
230 * by nsAutoMonitor::DestroyMonitor()
231 **/
232 static PRMonitor* NewMonitor(const char* name);
233 static void DestroyMonitor(PRMonitor* mon);
234
235
236 /**
237 * Constructor
238 * The constructor locks the given monitor. During destruction
239 * the monitor will be unlocked.
240 *
241 * @param mon A valid PRMonitor* returned from
242 * nsAutoMonitor::NewMonitor().
243 **/
244 nsAutoMonitor(PRMonitor* mon)
245 : nsAutoLockBase((void*)mon, eAutoMonitor),
246 mMonitor(mon), mLockCount(0)
247 {
248 NS_ASSERTION(mMonitor, "null monitor");
249 if (mMonitor) {
250 PR_EnterMonitor(mMonitor);
251 mLockCount = 1;
252 }
253 }
254
255 ~nsAutoMonitor() {
256 NS_ASSERTION(mMonitor, "null monitor");
257 if (mMonitor && mLockCount) {
258#ifdef DEBUG
259 PRStatus status =
260#endif
261 PR_ExitMonitor(mMonitor);
262 NS_ASSERTION(status == PR_SUCCESS, "PR_ExitMonitor failed");
263 }
264 }
265
266 /**
267 * Enter
268 * Client may call this to reenter the given monitor.
269 * @see prmon.h
270 **/
271 void Enter();
272
273 /**
274 * Exit
275 * Client may call this to exit the given monitor.
276 * @see prmon.h
277 **/
278 void Exit();
279
280 /**
281 * Wait
282 * @see prmon.h
283 **/
284 nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
285 return PR_Wait(mMonitor, interval) == PR_SUCCESS
286 ? NS_OK : NS_ERROR_FAILURE;
287 }
288
289 /**
290 * Notify
291 * @see prmon.h
292 **/
293 nsresult Notify() {
294 return PR_Notify(mMonitor) == PR_SUCCESS
295 ? NS_OK : NS_ERROR_FAILURE;
296 }
297
298 /**
299 * NotifyAll
300 * @see prmon.h
301 **/
302 nsresult NotifyAll() {
303 return PR_NotifyAll(mMonitor) == PR_SUCCESS
304 ? NS_OK : NS_ERROR_FAILURE;
305 }
306
307private:
308 PRMonitor* mMonitor;
309 PRInt32 mLockCount;
310
311 // Not meant to be implemented. This makes it a compiler error to
312 // construct or assign an nsAutoLock object incorrectly.
313 nsAutoMonitor(void) {}
314 nsAutoMonitor(nsAutoMonitor& /*aMon*/) {}
315 nsAutoMonitor& operator =(nsAutoMonitor& /*aMon*/) {
316 return *this;
317 }
318
319 // Not meant to be implemented. This makes it a compiler error to
320 // attempt to create an nsAutoLock object on the heap.
321 static void* operator new(size_t /*size*/) CPP_THROW_NEW {
322 return nsnull;
323 }
324 static void operator delete(void* /*memory*/) {}
325};
326
327////////////////////////////////////////////////////////////////////////////////
328// Once again, this time with a cache...
329// (Using this avoids the need to allocate a PRMonitor, which may be useful when
330// a large number of objects of the same class need associated monitors.)
331
332#include "prcmon.h"
333#include "nsError.h"
334
335class NS_COM nsAutoCMonitor : public nsAutoLockBase {
336public:
337 nsAutoCMonitor(void* lockObject)
338 : nsAutoLockBase(lockObject, eAutoCMonitor),
339 mLockObject(lockObject), mLockCount(0)
340 {
341 NS_ASSERTION(lockObject, "null lock object");
342 PR_CEnterMonitor(mLockObject);
343 mLockCount = 1;
344 }
345
346 ~nsAutoCMonitor() {
347 if (mLockCount) {
348#ifdef DEBUG
349 PRStatus status =
350#endif
351 PR_CExitMonitor(mLockObject);
352 NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
353 }
354 }
355
356 void Enter();
357 void Exit();
358
359 nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
360 return PR_CWait(mLockObject, interval) == PR_SUCCESS
361 ? NS_OK : NS_ERROR_FAILURE;
362 }
363
364 nsresult Notify() {
365 return PR_CNotify(mLockObject) == PR_SUCCESS
366 ? NS_OK : NS_ERROR_FAILURE;
367 }
368
369 nsresult NotifyAll() {
370 return PR_CNotifyAll(mLockObject) == PR_SUCCESS
371 ? NS_OK : NS_ERROR_FAILURE;
372 }
373
374private:
375 void* mLockObject;
376 PRInt32 mLockCount;
377
378 // Not meant to be implemented. This makes it a compiler error to
379 // construct or assign an nsAutoLock object incorrectly.
380 nsAutoCMonitor(void) {}
381 nsAutoCMonitor(nsAutoCMonitor& /*aMon*/) {}
382 nsAutoCMonitor& operator =(nsAutoCMonitor& /*aMon*/) {
383 return *this;
384 }
385
386 // Not meant to be implemented. This makes it a compiler error to
387 // attempt to create an nsAutoLock object on the heap.
388 static void* operator new(size_t /*size*/) CPP_THROW_NEW {
389 return nsnull;
390 }
391 static void operator delete(void* /*memory*/) {}
392};
393
394#endif // nsAutoLock_h__
395
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