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