1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_Monitor_h 8 #define mozilla_Monitor_h 9 10 #include "mozilla/CondVar.h" 11 #include "mozilla/Mutex.h" 12 13 namespace mozilla { 14 15 /** 16 * Monitor provides a *non*-reentrant monitor: *not* a Java-style 17 * monitor. If your code needs support for reentrancy, use 18 * ReentrantMonitor instead. (Rarely should reentrancy be needed.) 19 * 20 * Instead of directly calling Monitor methods, it's safer and simpler 21 * to instead use the RAII wrappers MonitorAutoLock and 22 * MonitorAutoUnlock. 23 */ 24 class Monitor 25 { 26 public: 27 explicit Monitor(const char* aName) 28 : mMutex(aName) 29 , mCondVar(mMutex, "[Monitor.mCondVar]") 30 { 31 } 32 33 ~Monitor() {} 34 35 void Lock() { mMutex.Lock(); } 36 void Unlock() { mMutex.Unlock(); } 37 38 nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT) 39 { 40 return mCondVar.Wait(aInterval); 41 } 42 43 nsresult Notify() { return mCondVar.Notify(); } 44 nsresult NotifyAll() { return mCondVar.NotifyAll(); } 45 46 void AssertCurrentThreadOwns() const 47 { 48 mMutex.AssertCurrentThreadOwns(); 49 } 50 51 void AssertNotCurrentThreadOwns() const 52 { 53 mMutex.AssertNotCurrentThreadOwns(); 54 } 55 56 private: 57 Monitor(); 58 Monitor(const Monitor&); 59 Monitor& operator=(const Monitor&); 60 61 Mutex mMutex; 62 CondVar mCondVar; 63 }; 64 65 /** 66 * Lock the monitor for the lexical scope instances of this class are 67 * bound to (except for MonitorAutoUnlock in nested scopes). 68 * 69 * The monitor must be unlocked when instances of this class are 70 * created. 71 */ 72 class MOZ_STACK_CLASS MonitorAutoLock 73 { 74 public: 75 explicit MonitorAutoLock(Monitor& aMonitor) 76 : mMonitor(&aMonitor) 77 { 78 mMonitor->Lock(); 79 } 80 81 ~MonitorAutoLock() 82 { 83 mMonitor->Unlock(); 84 } 85 86 nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT) 87 { 88 return mMonitor->Wait(aInterval); 89 } 90 91 nsresult Notify() { return mMonitor->Notify(); } 92 nsresult NotifyAll() { return mMonitor->NotifyAll(); } 93 94 private: 95 MonitorAutoLock(); 96 MonitorAutoLock(const MonitorAutoLock&); 97 MonitorAutoLock& operator=(const MonitorAutoLock&); 98 static void* operator new(size_t) CPP_THROW_NEW; 99 100 Monitor* mMonitor; 101 }; 102 103 /** 104 * Unlock the monitor for the lexical scope instances of this class 105 * are bound to (except for MonitorAutoLock in nested scopes). 106 * 107 * The monitor must be locked by the current thread when instances of 108 * this class are created. 109 */ 110 class MOZ_STACK_CLASS MonitorAutoUnlock 111 { 112 public: 113 explicit MonitorAutoUnlock(Monitor& aMonitor) 114 : mMonitor(&aMonitor) 115 { 116 mMonitor->Unlock(); 117 } 118 119 ~MonitorAutoUnlock() 120 { 121 mMonitor->Lock(); 122 } 123 124 private: 125 MonitorAutoUnlock(); 126 MonitorAutoUnlock(const MonitorAutoUnlock&); 127 MonitorAutoUnlock& operator=(const MonitorAutoUnlock&); 128 static void* operator new(size_t) CPP_THROW_NEW; 129 130 Monitor* mMonitor; 131 }; 132 133 } // namespace mozilla 134 135 #endif // mozilla_Monitor_h 136