/gecko_api/include/nsAutoLock.h
C Header | 449 lines | 195 code | 54 blank | 200 comment | 13 complexity | a320ed5672f0bbee8cebd52641da21f0 MD5 | raw file
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /* ***** BEGIN LICENSE BLOCK *****
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1
- *
- * The contents of this file are subject to the Mozilla Public License Version
- * 1.1 (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS" basis,
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- * for the specific language governing rights and limitations under the
- * License.
- *
- * The Original Code is mozilla.org code.
- *
- * The Initial Developer of the Original Code is
- * Netscape Communications Corporation.
- * Portions created by the Initial Developer are Copyright (C) 1998
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of the GNU General Public License Version 2 or later (the "GPL"),
- * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- * in which case the provisions of the GPL or the LGPL are applicable instead
- * of those above. If you wish to allow use of your version of this file only
- * under the terms of either the GPL or the LGPL, and not to allow others to
- * use your version of this file under the terms of the MPL, indicate your
- * decision by deleting the provisions above and replace them with the notice
- * and other provisions required by the GPL or the LGPL. If you do not delete
- * the provisions above, a recipient may use your version of this file under
- * the terms of any one of the MPL, the GPL or the LGPL.
- *
- * ***** END LICENSE BLOCK ***** */
- /*
- A stack-based lock object that makes using PRLock a bit more
- convenient. It acquires the monitor when constructed, and releases
- it when it goes out of scope.
- For example,
- class Foo {
- private:
- PRLock* mLock;
- public:
- Foo(void) {
- mLock = PR_NewLock();
- }
- ~Foo(void) {
- PR_DestroyLock(mLock);
- }
- void ThreadSafeMethod(void) {
- // we're don't hold the lock yet...
- nsAutoLock lock(mLock);
- // ...but now we do.
- // we even can do wacky stuff like return from arbitrary places w/o
- // worrying about forgetting to release the lock
- if (some_weird_condition)
- return;
- // otherwise do some other stuff
- }
- void ThreadSafeBlockScope(void) {
- // we're not in the lock here...
- {
- nsAutoLock lock(mLock);
- // but we are now, at least until the block scope closes
- }
- // ...now we're not in the lock anymore
- }
- };
- A similar stack-based locking object is available for PRMonitor. The
- major difference is that the PRMonitor must be created and destroyed
- via the static methods on nsAutoMonitor.
- For example:
- Foo::Foo() {
- mMon = nsAutoMonitor::NewMonitor("FooMonitor");
- }
- nsresult Foo::MyMethod(...) {
- nsAutoMonitor mon(mMon);
- ...
- // go ahead and do deeply nested returns...
- return NS_ERROR_FAILURE;
- ...
- // or call Wait or Notify...
- mon.Wait();
- ...
- // cleanup is automatic
- }
- */
- #ifndef nsAutoLock_h__
- #define nsAutoLock_h__
- #include "nscore.h"
- #include "prlock.h"
- #include "prlog.h"
- /**
- * nsAutoLockBase
- * This is the base class for the stack-based locking objects.
- * Clients of derived classes need not play with this superclass.
- **/
- class NS_COM_GLUE nsAutoLockBase {
- friend class nsAutoUnlockBase;
- protected:
- nsAutoLockBase() {}
- enum nsAutoLockType {eAutoLock, eAutoMonitor, eAutoCMonitor};
- #ifdef DEBUG
- nsAutoLockBase(void* addr, nsAutoLockType type);
- ~nsAutoLockBase();
- void Show();
- void Hide();
- void* mAddr;
- nsAutoLockBase* mDown;
- nsAutoLockType mType;
- #else
- nsAutoLockBase(void* addr, nsAutoLockType type) {}
- ~nsAutoLockBase() {}
- void Show() {}
- void Hide() {}
- #endif
- };
- /**
- * nsAutoUnlockBase
- * This is the base class for stack-based unlocking objects.
- * It unlocks locking objects based on nsAutoLockBase.
- **/
- class NS_COM_GLUE nsAutoUnlockBase {
- protected:
- nsAutoUnlockBase() {}
- #ifdef DEBUG
- nsAutoUnlockBase(void* addr);
- ~nsAutoUnlockBase();
- nsAutoLockBase* mLock;
- #else
- nsAutoUnlockBase(void* addr) {}
- ~nsAutoUnlockBase() {}
- #endif
- };
- /**
- * nsAutoLock
- * Stack-based locking object for PRLock.
- **/
- class NS_COM_GLUE nsAutoLock : public nsAutoLockBase {
- private:
- PRLock* mLock;
- PRBool mLocked;
- // Not meant to be implemented. This makes it a compiler error to
- // construct or assign an nsAutoLock object incorrectly.
- nsAutoLock(void) {}
- nsAutoLock(nsAutoLock& /*aLock*/) {}
- nsAutoLock& operator =(nsAutoLock& /*aLock*/) {
- return *this;
- }
- // Not meant to be implemented. This makes it a compiler error to
- // attempt to create an nsAutoLock object on the heap.
- static void* operator new(size_t /*size*/) CPP_THROW_NEW {
- return nsnull;
- }
- static void operator delete(void* /*memory*/) {}
- public:
- /**
- * NewLock
- * Allocates a new PRLock for use with nsAutoLock. name is
- * not checked for uniqueness.
- * @param name A name which can reference this lock
- * @param lock A valid PRLock* that was created by nsAutoLock::NewLock()
- * @returns nsnull if failure
- * A valid PRLock* if successful, which must be destroyed
- * by nsAutoLock::DestroyLock()
- **/
- static PRLock* NewLock(const char* name);
- static void DestroyLock(PRLock* lock);
- /**
- * Constructor
- * The constructor aquires the given lock. The destructor
- * releases the lock.
- *
- * @param aLock A valid PRLock* returned from the NSPR's
- * PR_NewLock() function.
- **/
- nsAutoLock(PRLock* aLock)
- : nsAutoLockBase(aLock, eAutoLock),
- mLock(aLock),
- mLocked(PR_TRUE) {
- PR_ASSERT(mLock);
- // This will assert deep in the bowels of NSPR if you attempt
- // to re-enter the lock.
- PR_Lock(mLock);
- }
-
- ~nsAutoLock(void) {
- if (mLocked)
- PR_Unlock(mLock);
- }
- /**
- * lock
- * Client may call this to reaquire the given lock. Take special
- * note that attempting to aquire a locked lock will hang or crash.
- **/
- void lock() {
- Show();
- PR_ASSERT(!mLocked);
- PR_Lock(mLock);
- mLocked = PR_TRUE;
- }
- /**
- * unlock
- * Client may call this to release the given lock. Take special
- * note unlocking an unlocked lock has undefined results.
- **/
- void unlock() {
- PR_ASSERT(mLocked);
- PR_Unlock(mLock);
- mLocked = PR_FALSE;
- Hide();
- }
- };
- class nsAutoUnlock : nsAutoUnlockBase
- {
- private:
- PRLock *mLock;
-
- public:
- nsAutoUnlock(PRLock *lock) :
- nsAutoUnlockBase(lock),
- mLock(lock)
- {
- PR_Unlock(mLock);
- }
- ~nsAutoUnlock() {
- PR_Lock(mLock);
- }
- };
- #include "prcmon.h"
- #include "nsError.h"
- #include "nsDebug.h"
- class NS_COM_GLUE nsAutoMonitor : public nsAutoLockBase {
- public:
- /**
- * NewMonitor
- * Allocates a new PRMonitor for use with nsAutoMonitor.
- * @param name A (unique /be?) name which can reference this monitor
- * @returns nsnull if failure
- * A valid PRMonitor* is successful while must be destroyed
- * by nsAutoMonitor::DestroyMonitor()
- **/
- static PRMonitor* NewMonitor(const char* name);
- static void DestroyMonitor(PRMonitor* mon);
-
- /**
- * Constructor
- * The constructor locks the given monitor. During destruction
- * the monitor will be unlocked.
- *
- * @param mon A valid PRMonitor* returned from
- * nsAutoMonitor::NewMonitor().
- **/
- nsAutoMonitor(PRMonitor* mon)
- : nsAutoLockBase((void*)mon, eAutoMonitor),
- mMonitor(mon), mLockCount(0)
- {
- NS_ASSERTION(mMonitor, "null monitor");
- if (mMonitor) {
- PR_EnterMonitor(mMonitor);
- mLockCount = 1;
- }
- }
- ~nsAutoMonitor() {
- NS_ASSERTION(mMonitor, "null monitor");
- if (mMonitor && mLockCount) {
- #ifdef DEBUG
- PRStatus status =
- #endif
- PR_ExitMonitor(mMonitor);
- NS_ASSERTION(status == PR_SUCCESS, "PR_ExitMonitor failed");
- }
- }
- /**
- * Enter
- * Client may call this to reenter the given monitor.
- * @see prmon.h
- **/
- void Enter();
- /**
- * Exit
- * Client may call this to exit the given monitor.
- * @see prmon.h
- **/
- void Exit();
- /**
- * Wait
- * @see prmon.h
- **/
- nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
- return PR_Wait(mMonitor, interval) == PR_SUCCESS
- ? NS_OK : NS_ERROR_FAILURE;
- }
- /**
- * Notify
- * @see prmon.h
- **/
- nsresult Notify() {
- return PR_Notify(mMonitor) == PR_SUCCESS
- ? NS_OK : NS_ERROR_FAILURE;
- }
- /**
- * NotifyAll
- * @see prmon.h
- **/
- nsresult NotifyAll() {
- return PR_NotifyAll(mMonitor) == PR_SUCCESS
- ? NS_OK : NS_ERROR_FAILURE;
- }
- private:
- PRMonitor* mMonitor;
- PRInt32 mLockCount;
- // Not meant to be implemented. This makes it a compiler error to
- // construct or assign an nsAutoLock object incorrectly.
- nsAutoMonitor(void) {}
- nsAutoMonitor(nsAutoMonitor& /*aMon*/) {}
- nsAutoMonitor& operator =(nsAutoMonitor& /*aMon*/) {
- return *this;
- }
- // Not meant to be implemented. This makes it a compiler error to
- // attempt to create an nsAutoLock object on the heap.
- static void* operator new(size_t /*size*/) CPP_THROW_NEW {
- return nsnull;
- }
- static void operator delete(void* /*memory*/) {}
- };
- ////////////////////////////////////////////////////////////////////////////////
- // Once again, this time with a cache...
- // (Using this avoids the need to allocate a PRMonitor, which may be useful when
- // a large number of objects of the same class need associated monitors.)
- #include "prcmon.h"
- #include "nsError.h"
- class NS_COM_GLUE nsAutoCMonitor : public nsAutoLockBase {
- public:
- nsAutoCMonitor(void* lockObject)
- : nsAutoLockBase(lockObject, eAutoCMonitor),
- mLockObject(lockObject), mLockCount(0)
- {
- NS_ASSERTION(lockObject, "null lock object");
- PR_CEnterMonitor(mLockObject);
- mLockCount = 1;
- }
- ~nsAutoCMonitor() {
- if (mLockCount) {
- #ifdef DEBUG
- PRStatus status =
- #endif
- PR_CExitMonitor(mLockObject);
- NS_ASSERTION(status == PR_SUCCESS, "PR_CExitMonitor failed");
- }
- }
- void Enter();
- void Exit();
- nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) {
- return PR_CWait(mLockObject, interval) == PR_SUCCESS
- ? NS_OK : NS_ERROR_FAILURE;
- }
- nsresult Notify() {
- return PR_CNotify(mLockObject) == PR_SUCCESS
- ? NS_OK : NS_ERROR_FAILURE;
- }
- nsresult NotifyAll() {
- return PR_CNotifyAll(mLockObject) == PR_SUCCESS
- ? NS_OK : NS_ERROR_FAILURE;
- }
- private:
- void* mLockObject;
- PRInt32 mLockCount;
- // Not meant to be implemented. This makes it a compiler error to
- // construct or assign an nsAutoLock object incorrectly.
- nsAutoCMonitor(void) {}
- nsAutoCMonitor(nsAutoCMonitor& /*aMon*/) {}
- nsAutoCMonitor& operator =(nsAutoCMonitor& /*aMon*/) {
- return *this;
- }
- // Not meant to be implemented. This makes it a compiler error to
- // attempt to create an nsAutoLock object on the heap.
- static void* operator new(size_t /*size*/) CPP_THROW_NEW {
- return nsnull;
- }
- static void operator delete(void* /*memory*/) {}
- };
- #endif // nsAutoLock_h__