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
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/
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
15 * The Original Code is mozilla.org code.
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.
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.
36 * ***** END LICENSE BLOCK ***** */
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.
56 PR_DestroyLock(mLock);
59 void ThreadSafeMethod(void) {
60 // we're don't hold the lock yet...
62 nsAutoLock lock(mLock);
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)
70 // otherwise do some other stuff
73 void ThreadSafeBlockScope(void) {
74 // we're not in the lock here...
77 nsAutoLock lock(mLock);
78 // but we are now, at least until the block scope closes
81 // ...now we're not in the lock anymore
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.
91 mMon = nsAutoMonitor::NewMonitor("FooMonitor");
93 nsresult Foo::MyMethod(...) {
94 nsAutoMonitor mon(mMon);
96 // go ahead and do deeply nested returns...
97 return NS_ERROR_FAILURE;
99 // or call Wait or Notify...
102 // cleanup is automatic
106 #ifndef nsAutoLock_h__
107 #define nsAutoLock_h__
112 #include "mozilla/AutoRestore.h"
116 * This is the base class for the stack-based locking objects.
117 * Clients of derived classes need not play with this superclass.
119 class NS_COM_GLUE NS_STACK_CLASS nsAutoLockBase
{
120 friend class nsAutoUnlockBase
;
124 enum nsAutoLockType
{eAutoLock
, eAutoMonitor
, eAutoCMonitor
};
127 nsAutoLockBase(void* addr
, nsAutoLockType type
);
134 nsAutoLockBase
* mDown
;
135 nsAutoLockType mType
;
137 nsAutoLockBase(void* addr
, nsAutoLockType type
) {}
147 * This is the base class for stack-based unlocking objects.
148 * It unlocks locking objects based on nsAutoLockBase.
150 class NS_COM_GLUE NS_STACK_CLASS nsAutoUnlockBase
{
152 nsAutoUnlockBase() {}
155 nsAutoUnlockBase(void* addr
);
158 nsAutoLockBase
* mLock
;
160 nsAutoUnlockBase(void* addr
) {}
161 ~nsAutoUnlockBase() {}
167 * Stack-based locking object for PRLock.
169 class NS_COM_GLUE NS_STACK_CLASS nsAutoLock
: public nsAutoLockBase
{
173 MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
175 // Not meant to be implemented. This makes it a compiler error to
176 // construct or assign an nsAutoLock object incorrectly.
178 nsAutoLock(nsAutoLock
& /*aLock*/) {}
179 nsAutoLock
& operator =(nsAutoLock
& /*aLock*/) {
183 // Not meant to be implemented. This makes it a compiler error to
184 // attempt to create an nsAutoLock object on the heap.
185 static void* operator new(size_t /*size*/) CPP_THROW_NEW
{
188 static void operator delete(void* /*memory*/) {}
194 * Allocates a new PRLock for use with nsAutoLock. name is
195 * not checked for uniqueness.
196 * @param name A name which can reference this lock
197 * @param lock A valid PRLock* that was created by nsAutoLock::NewLock()
198 * @returns nsnull if failure
199 * A valid PRLock* if successful, which must be destroyed
200 * by nsAutoLock::DestroyLock()
202 static PRLock
* NewLock(const char* name
);
203 static void DestroyLock(PRLock
* lock
);
207 * The constructor aquires the given lock. The destructor
210 * @param aLock A valid PRLock* returned from the NSPR's
211 * PR_NewLock() function.
213 nsAutoLock(PRLock
* aLock MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM
)
214 : nsAutoLockBase(aLock
, eAutoLock
),
217 MOZILLA_GUARD_OBJECT_NOTIFIER_INIT
;
220 // This will assert deep in the bowels of NSPR if you attempt
221 // to re-enter the lock.
232 * Client may call this to reaquire the given lock. Take special
233 * note that attempting to aquire a locked lock will hang or crash.
245 * Client may call this to release the given lock. Take special
246 * note unlocking an unlocked lock has undefined results.
256 class NS_STACK_CLASS nsAutoUnlock
: private nsAutoUnlockBase
260 MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
263 nsAutoUnlock(PRLock
*lock MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM
) :
264 nsAutoUnlockBase(lock
),
267 MOZILLA_GUARD_OBJECT_NOTIFIER_INIT
;
280 class NS_COM_GLUE NS_STACK_CLASS nsAutoMonitor
: public nsAutoLockBase
{
285 * Allocates a new PRMonitor for use with nsAutoMonitor.
286 * @param name A (unique /be?) name which can reference this monitor
287 * @returns nsnull if failure
288 * A valid PRMonitor* is successful while must be destroyed
289 * by nsAutoMonitor::DestroyMonitor()
291 static PRMonitor
* NewMonitor(const char* name
);
292 static void DestroyMonitor(PRMonitor
* mon
);
297 * The constructor locks the given monitor. During destruction
298 * the monitor will be unlocked.
300 * @param mon A valid PRMonitor* returned from
301 * nsAutoMonitor::NewMonitor().
303 nsAutoMonitor(PRMonitor
* mon MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM
)
304 : nsAutoLockBase((void*)mon
, eAutoMonitor
),
305 mMonitor(mon
), mLockCount(0)
307 MOZILLA_GUARD_OBJECT_NOTIFIER_INIT
;
308 NS_ASSERTION(mMonitor
, "null monitor");
310 PR_EnterMonitor(mMonitor
);
316 NS_ASSERTION(mMonitor
, "null monitor");
317 if (mMonitor
&& mLockCount
) {
321 PR_ExitMonitor(mMonitor
);
322 NS_ASSERTION(status
== PR_SUCCESS
, "PR_ExitMonitor failed");
328 * Client may call this to reenter the given monitor.
335 * Client may call this to exit the given monitor.
344 nsresult
Wait(PRIntervalTime interval
= PR_INTERVAL_NO_TIMEOUT
) {
345 return PR_Wait(mMonitor
, interval
) == PR_SUCCESS
346 ? NS_OK
: NS_ERROR_FAILURE
;
354 return PR_Notify(mMonitor
) == PR_SUCCESS
355 ? NS_OK
: NS_ERROR_FAILURE
;
362 nsresult
NotifyAll() {
363 return PR_NotifyAll(mMonitor
) == PR_SUCCESS
364 ? NS_OK
: NS_ERROR_FAILURE
;
370 MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
372 // Not meant to be implemented. This makes it a compiler error to
373 // construct or assign an nsAutoLock object incorrectly.
374 nsAutoMonitor(void) {}
375 nsAutoMonitor(nsAutoMonitor
& /*aMon*/) {}
376 nsAutoMonitor
& operator =(nsAutoMonitor
& /*aMon*/) {
380 // Not meant to be implemented. This makes it a compiler error to
381 // attempt to create an nsAutoLock object on the heap.
382 static void* operator new(size_t /*size*/) CPP_THROW_NEW
{
385 static void operator delete(void* /*memory*/) {}
388 ////////////////////////////////////////////////////////////////////////////////
389 // Once again, this time with a cache...
390 // (Using this avoids the need to allocate a PRMonitor, which may be useful when
391 // a large number of objects of the same class need associated monitors.)
396 class NS_COM_GLUE NS_STACK_CLASS nsAutoCMonitor
: public nsAutoLockBase
{
398 nsAutoCMonitor(void* lockObject MOZILLA_GUARD_OBJECT_NOTIFIER_PARAM
)
399 : nsAutoLockBase(lockObject
, eAutoCMonitor
),
400 mLockObject(lockObject
), mLockCount(0)
402 MOZILLA_GUARD_OBJECT_NOTIFIER_INIT
;
403 NS_ASSERTION(lockObject
, "null lock object");
404 PR_CEnterMonitor(mLockObject
);
413 PR_CExitMonitor(mLockObject
);
414 NS_ASSERTION(status
== PR_SUCCESS
, "PR_CExitMonitor failed");
421 nsresult
Wait(PRIntervalTime interval
= PR_INTERVAL_NO_TIMEOUT
) {
422 return PR_CWait(mLockObject
, interval
) == PR_SUCCESS
423 ? NS_OK
: NS_ERROR_FAILURE
;
427 return PR_CNotify(mLockObject
) == PR_SUCCESS
428 ? NS_OK
: NS_ERROR_FAILURE
;
431 nsresult
NotifyAll() {
432 return PR_CNotifyAll(mLockObject
) == PR_SUCCESS
433 ? NS_OK
: NS_ERROR_FAILURE
;
439 MOZILLA_DECL_USE_GUARD_OBJECT_NOTIFIER
441 // Not meant to be implemented. This makes it a compiler error to
442 // construct or assign an nsAutoLock object incorrectly.
443 nsAutoCMonitor(void) {}
444 nsAutoCMonitor(nsAutoCMonitor
& /*aMon*/) {}
445 nsAutoCMonitor
& operator =(nsAutoCMonitor
& /*aMon*/) {
449 // Not meant to be implemented. This makes it a compiler error to
450 // attempt to create an nsAutoLock object on the heap.
451 static void* operator new(size_t /*size*/) CPP_THROW_NEW
{
454 static void operator delete(void* /*memory*/) {}
457 #endif // nsAutoLock_h__