Line data Source code
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 160 : explicit Monitor(const char* aName)
28 160 : : mMutex(aName)
29 160 : , mCondVar(mMutex, "[Monitor.mCondVar]")
30 : {
31 160 : }
32 :
33 2 : ~Monitor() {}
34 :
35 8094 : void Lock() { mMutex.Lock(); }
36 8068 : void Unlock() { mMutex.Unlock(); }
37 :
38 446 : nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT)
39 : {
40 446 : return mCondVar.Wait(aInterval);
41 : }
42 :
43 351 : nsresult Notify() { return mCondVar.Notify(); }
44 147 : nsresult NotifyAll() { return mCondVar.NotifyAll(); }
45 :
46 10460 : void AssertCurrentThreadOwns() const
47 : {
48 10460 : mMutex.AssertCurrentThreadOwns();
49 10460 : }
50 :
51 1002 : void AssertNotCurrentThreadOwns() const
52 : {
53 1002 : mMutex.AssertNotCurrentThreadOwns();
54 1002 : }
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 7458 : explicit MonitorAutoLock(Monitor& aMonitor)
76 7458 : : mMonitor(&aMonitor)
77 : {
78 7458 : mMonitor->Lock();
79 7459 : }
80 :
81 7429 : ~MonitorAutoLock()
82 7430 : {
83 7429 : mMonitor->Unlock();
84 7430 : }
85 :
86 57 : nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT)
87 : {
88 57 : return mMonitor->Wait(aInterval);
89 : }
90 :
91 80 : nsresult Notify() { return mMonitor->Notify(); }
92 17 : 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 : friend class MonitorAutoUnlock;
101 :
102 : Monitor* mMonitor;
103 : };
104 :
105 : /**
106 : * Unlock the monitor for the lexical scope instances of this class
107 : * are bound to (except for MonitorAutoLock in nested scopes).
108 : *
109 : * The monitor must be locked by the current thread when instances of
110 : * this class are created.
111 : */
112 : class MOZ_STACK_CLASS MonitorAutoUnlock
113 : {
114 : public:
115 639 : explicit MonitorAutoUnlock(Monitor& aMonitor)
116 639 : : mMonitor(&aMonitor)
117 : {
118 639 : mMonitor->Unlock();
119 639 : }
120 :
121 : explicit MonitorAutoUnlock(MonitorAutoLock& aMonitorLock)
122 : : mMonitor(aMonitorLock.mMonitor)
123 : {
124 : mMonitor->Unlock();
125 : }
126 :
127 636 : ~MonitorAutoUnlock()
128 636 : {
129 636 : mMonitor->Lock();
130 636 : }
131 :
132 : private:
133 : MonitorAutoUnlock();
134 : MonitorAutoUnlock(const MonitorAutoUnlock&);
135 : MonitorAutoUnlock& operator=(const MonitorAutoUnlock&);
136 : static void* operator new(size_t) CPP_THROW_NEW;
137 :
138 : Monitor* mMonitor;
139 : };
140 :
141 : } // namespace mozilla
142 :
143 : #endif // mozilla_Monitor_h
|