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_ReentrantMonitor_h
8 : #define mozilla_ReentrantMonitor_h
9 :
10 : #include "prmon.h"
11 :
12 : #ifdef MOZILLA_INTERNAL_API
13 : #include "GeckoProfiler.h"
14 : #endif //MOZILLA_INTERNAL_API
15 :
16 : #include "mozilla/BlockingResourceBase.h"
17 :
18 : //
19 : // Provides:
20 : //
21 : // - ReentrantMonitor, a Java-like monitor
22 : // - ReentrantMonitorAutoEnter, an RAII class for ensuring that
23 : // ReentrantMonitors are properly entered and exited
24 : //
25 : // Using ReentrantMonitorAutoEnter is MUCH preferred to making bare calls to
26 : // ReentrantMonitor.Enter and Exit.
27 : //
28 : namespace mozilla {
29 :
30 :
31 : /**
32 : * ReentrantMonitor
33 : * Java-like monitor.
34 : * When possible, use ReentrantMonitorAutoEnter to hold this monitor within a
35 : * scope, instead of calling Enter/Exit directly.
36 : **/
37 : class ReentrantMonitor : BlockingResourceBase
38 : {
39 : public:
40 : /**
41 : * ReentrantMonitor
42 : * @param aName A name which can reference this monitor
43 : */
44 277 : explicit ReentrantMonitor(const char* aName)
45 277 : : BlockingResourceBase(aName, eReentrantMonitor)
46 : #ifdef DEBUG
47 277 : , mEntryCount(0)
48 : #endif
49 : {
50 277 : MOZ_COUNT_CTOR(ReentrantMonitor);
51 277 : mReentrantMonitor = PR_NewMonitor();
52 277 : if (!mReentrantMonitor) {
53 0 : MOZ_CRASH("Can't allocate mozilla::ReentrantMonitor");
54 : }
55 277 : }
56 :
57 : /**
58 : * ~ReentrantMonitor
59 : **/
60 232 : ~ReentrantMonitor()
61 232 : {
62 232 : NS_ASSERTION(mReentrantMonitor,
63 : "improperly constructed ReentrantMonitor or double free");
64 232 : PR_DestroyMonitor(mReentrantMonitor);
65 232 : mReentrantMonitor = 0;
66 232 : MOZ_COUNT_DTOR(ReentrantMonitor);
67 232 : }
68 :
69 : #ifndef DEBUG
70 : /**
71 : * Enter
72 : * @see prmon.h
73 : **/
74 : void Enter() { PR_EnterMonitor(mReentrantMonitor); }
75 :
76 : /**
77 : * Exit
78 : * @see prmon.h
79 : **/
80 : void Exit() { PR_ExitMonitor(mReentrantMonitor); }
81 :
82 : /**
83 : * Wait
84 : * @see prmon.h
85 : **/
86 : nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT)
87 : {
88 : #ifdef MOZILLA_INTERNAL_API
89 : AutoProfilerThreadSleep sleep;
90 : #endif //MOZILLA_INTERNAL_API
91 : return PR_Wait(mReentrantMonitor, aInterval) == PR_SUCCESS ?
92 : NS_OK : NS_ERROR_FAILURE;
93 : }
94 :
95 : #else // ifndef DEBUG
96 : void Enter();
97 : void Exit();
98 : nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT);
99 :
100 : #endif // ifndef DEBUG
101 :
102 : /**
103 : * Notify
104 : * @see prmon.h
105 : **/
106 56 : nsresult Notify()
107 : {
108 56 : return PR_Notify(mReentrantMonitor) == PR_SUCCESS ? NS_OK :
109 56 : NS_ERROR_FAILURE;
110 : }
111 :
112 : /**
113 : * NotifyAll
114 : * @see prmon.h
115 : **/
116 0 : nsresult NotifyAll()
117 : {
118 0 : return PR_NotifyAll(mReentrantMonitor) == PR_SUCCESS ? NS_OK :
119 0 : NS_ERROR_FAILURE;
120 : }
121 :
122 : #ifdef DEBUG
123 : /**
124 : * AssertCurrentThreadIn
125 : * @see prmon.h
126 : **/
127 6685 : void AssertCurrentThreadIn()
128 : {
129 6685 : PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor);
130 6685 : }
131 :
132 : /**
133 : * AssertNotCurrentThreadIn
134 : * @see prmon.h
135 : **/
136 36 : void AssertNotCurrentThreadIn()
137 : {
138 : // FIXME bug 476536
139 36 : }
140 :
141 : #else
142 : void AssertCurrentThreadIn() {}
143 : void AssertNotCurrentThreadIn() {}
144 :
145 : #endif // ifdef DEBUG
146 :
147 : private:
148 : ReentrantMonitor();
149 : ReentrantMonitor(const ReentrantMonitor&);
150 : ReentrantMonitor& operator=(const ReentrantMonitor&);
151 :
152 : PRMonitor* mReentrantMonitor;
153 : #ifdef DEBUG
154 : int32_t mEntryCount;
155 : #endif
156 : };
157 :
158 :
159 : /**
160 : * ReentrantMonitorAutoEnter
161 : * Enters the ReentrantMonitor when it enters scope, and exits it when
162 : * it leaves scope.
163 : *
164 : * MUCH PREFERRED to bare calls to ReentrantMonitor.Enter and Exit.
165 : */
166 : class MOZ_STACK_CLASS ReentrantMonitorAutoEnter
167 : {
168 : public:
169 : /**
170 : * Constructor
171 : * The constructor aquires the given lock. The destructor
172 : * releases the lock.
173 : *
174 : * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*.
175 : **/
176 8398 : explicit ReentrantMonitorAutoEnter(mozilla::ReentrantMonitor& aReentrantMonitor)
177 8398 : : mReentrantMonitor(&aReentrantMonitor)
178 : {
179 8398 : NS_ASSERTION(mReentrantMonitor, "null monitor");
180 8398 : mReentrantMonitor->Enter();
181 8398 : }
182 :
183 8398 : ~ReentrantMonitorAutoEnter(void)
184 8398 : {
185 8398 : mReentrantMonitor->Exit();
186 8398 : }
187 :
188 56 : nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT)
189 : {
190 56 : return mReentrantMonitor->Wait(aInterval);
191 : }
192 :
193 56 : nsresult Notify() { return mReentrantMonitor->Notify(); }
194 0 : nsresult NotifyAll() { return mReentrantMonitor->NotifyAll(); }
195 :
196 : private:
197 : ReentrantMonitorAutoEnter();
198 : ReentrantMonitorAutoEnter(const ReentrantMonitorAutoEnter&);
199 : ReentrantMonitorAutoEnter& operator=(const ReentrantMonitorAutoEnter&);
200 : static void* operator new(size_t) CPP_THROW_NEW;
201 :
202 : friend class ReentrantMonitorAutoExit;
203 :
204 : mozilla::ReentrantMonitor* mReentrantMonitor;
205 : };
206 :
207 : /**
208 : * ReentrantMonitorAutoExit
209 : * Exit the ReentrantMonitor when it enters scope, and enters it when it leaves
210 : * scope.
211 : *
212 : * MUCH PREFERRED to bare calls to ReentrantMonitor.Exit and Enter.
213 : */
214 : class MOZ_STACK_CLASS ReentrantMonitorAutoExit
215 : {
216 : public:
217 : /**
218 : * Constructor
219 : * The constructor releases the given lock. The destructor
220 : * acquires the lock. The lock must be held before constructing
221 : * this object!
222 : *
223 : * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*. It
224 : * must be already locked.
225 : **/
226 0 : explicit ReentrantMonitorAutoExit(ReentrantMonitor& aReentrantMonitor)
227 0 : : mReentrantMonitor(&aReentrantMonitor)
228 : {
229 0 : NS_ASSERTION(mReentrantMonitor, "null monitor");
230 0 : mReentrantMonitor->AssertCurrentThreadIn();
231 0 : mReentrantMonitor->Exit();
232 0 : }
233 :
234 : explicit ReentrantMonitorAutoExit(
235 : ReentrantMonitorAutoEnter& aReentrantMonitorAutoEnter)
236 : : mReentrantMonitor(aReentrantMonitorAutoEnter.mReentrantMonitor)
237 : {
238 : NS_ASSERTION(mReentrantMonitor, "null monitor");
239 : mReentrantMonitor->AssertCurrentThreadIn();
240 : mReentrantMonitor->Exit();
241 : }
242 :
243 0 : ~ReentrantMonitorAutoExit(void)
244 0 : {
245 0 : mReentrantMonitor->Enter();
246 0 : }
247 :
248 : private:
249 : ReentrantMonitorAutoExit();
250 : ReentrantMonitorAutoExit(const ReentrantMonitorAutoExit&);
251 : ReentrantMonitorAutoExit& operator=(const ReentrantMonitorAutoExit&);
252 : static void* operator new(size_t) CPP_THROW_NEW;
253 :
254 : ReentrantMonitor* mReentrantMonitor;
255 : };
256 :
257 : } // namespace mozilla
258 :
259 :
260 : #endif // ifndef mozilla_ReentrantMonitor_h
|