michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * vim: sw=2 ts=8 et : michael@0: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_Monitor_h michael@0: #define mozilla_Monitor_h michael@0: michael@0: #include "mozilla/CondVar.h" michael@0: #include "mozilla/Mutex.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: /** michael@0: * Monitor provides a *non*-reentrant monitor: *not* a Java-style michael@0: * monitor. If your code needs support for reentrancy, use michael@0: * ReentrantMonitor instead. (Rarely should reentrancy be needed.) michael@0: * michael@0: * Instead of directly calling Monitor methods, it's safer and simpler michael@0: * to instead use the RAII wrappers MonitorAutoLock and michael@0: * MonitorAutoUnlock. michael@0: */ michael@0: class NS_COM_GLUE Monitor michael@0: { michael@0: public: michael@0: Monitor(const char* aName) : michael@0: mMutex(aName), michael@0: mCondVar(mMutex, "[Monitor.mCondVar]") michael@0: {} michael@0: michael@0: ~Monitor() {} michael@0: michael@0: void Lock() michael@0: { michael@0: mMutex.Lock(); michael@0: } michael@0: michael@0: void Unlock() michael@0: { michael@0: mMutex.Unlock(); michael@0: } michael@0: michael@0: nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) michael@0: { michael@0: return mCondVar.Wait(interval); michael@0: } michael@0: michael@0: nsresult Notify() michael@0: { michael@0: return mCondVar.Notify(); michael@0: } michael@0: michael@0: nsresult NotifyAll() michael@0: { michael@0: return mCondVar.NotifyAll(); michael@0: } michael@0: michael@0: void AssertCurrentThreadOwns() const michael@0: { michael@0: mMutex.AssertCurrentThreadOwns(); michael@0: } michael@0: michael@0: void AssertNotCurrentThreadOwns() const michael@0: { michael@0: mMutex.AssertNotCurrentThreadOwns(); michael@0: } michael@0: michael@0: private: michael@0: Monitor(); michael@0: Monitor(const Monitor&); michael@0: Monitor& operator =(const Monitor&); michael@0: michael@0: Mutex mMutex; michael@0: CondVar mCondVar; michael@0: }; michael@0: michael@0: /** michael@0: * Lock the monitor for the lexical scope instances of this class are michael@0: * bound to (except for MonitorAutoUnlock in nested scopes). michael@0: * michael@0: * The monitor must be unlocked when instances of this class are michael@0: * created. michael@0: */ michael@0: class NS_COM_GLUE MOZ_STACK_CLASS MonitorAutoLock michael@0: { michael@0: public: michael@0: MonitorAutoLock(Monitor& aMonitor) : michael@0: mMonitor(&aMonitor) michael@0: { michael@0: mMonitor->Lock(); michael@0: } michael@0: michael@0: ~MonitorAutoLock() michael@0: { michael@0: mMonitor->Unlock(); michael@0: } michael@0: michael@0: nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) michael@0: { michael@0: return mMonitor->Wait(interval); michael@0: } michael@0: michael@0: nsresult Notify() michael@0: { michael@0: return mMonitor->Notify(); michael@0: } michael@0: michael@0: nsresult NotifyAll() michael@0: { michael@0: return mMonitor->NotifyAll(); michael@0: } michael@0: michael@0: private: michael@0: MonitorAutoLock(); michael@0: MonitorAutoLock(const MonitorAutoLock&); michael@0: MonitorAutoLock& operator =(const MonitorAutoLock&); michael@0: static void* operator new(size_t) CPP_THROW_NEW; michael@0: static void operator delete(void*); michael@0: michael@0: Monitor* mMonitor; michael@0: }; michael@0: michael@0: /** michael@0: * Unlock the monitor for the lexical scope instances of this class michael@0: * are bound to (except for MonitorAutoLock in nested scopes). michael@0: * michael@0: * The monitor must be locked by the current thread when instances of michael@0: * this class are created. michael@0: */ michael@0: class NS_COM_GLUE MOZ_STACK_CLASS MonitorAutoUnlock michael@0: { michael@0: public: michael@0: MonitorAutoUnlock(Monitor& aMonitor) : michael@0: mMonitor(&aMonitor) michael@0: { michael@0: mMonitor->Unlock(); michael@0: } michael@0: michael@0: ~MonitorAutoUnlock() michael@0: { michael@0: mMonitor->Lock(); michael@0: } michael@0: michael@0: private: michael@0: MonitorAutoUnlock(); michael@0: MonitorAutoUnlock(const MonitorAutoUnlock&); michael@0: MonitorAutoUnlock& operator =(const MonitorAutoUnlock&); michael@0: static void* operator new(size_t) CPP_THROW_NEW; michael@0: static void operator delete(void*); michael@0: michael@0: Monitor* mMonitor; michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_Monitor_h