|
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- |
|
2 * vim: sw=4 ts=4 et : |
|
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 NS_COM_GLUE ReentrantMonitor : BlockingResourceBase |
|
38 { |
|
39 public: |
|
40 /** |
|
41 * ReentrantMonitor |
|
42 * @param aName A name which can reference this monitor |
|
43 */ |
|
44 ReentrantMonitor(const char* aName) : |
|
45 BlockingResourceBase(aName, eReentrantMonitor) |
|
46 #ifdef DEBUG |
|
47 , mEntryCount(0) |
|
48 #endif |
|
49 { |
|
50 MOZ_COUNT_CTOR(ReentrantMonitor); |
|
51 mReentrantMonitor = PR_NewMonitor(); |
|
52 if (!mReentrantMonitor) |
|
53 NS_RUNTIMEABORT("Can't allocate mozilla::ReentrantMonitor"); |
|
54 } |
|
55 |
|
56 /** |
|
57 * ~ReentrantMonitor |
|
58 **/ |
|
59 ~ReentrantMonitor() |
|
60 { |
|
61 NS_ASSERTION(mReentrantMonitor, |
|
62 "improperly constructed ReentrantMonitor or double free"); |
|
63 PR_DestroyMonitor(mReentrantMonitor); |
|
64 mReentrantMonitor = 0; |
|
65 MOZ_COUNT_DTOR(ReentrantMonitor); |
|
66 } |
|
67 |
|
68 #ifndef DEBUG |
|
69 /** |
|
70 * Enter |
|
71 * @see prmon.h |
|
72 **/ |
|
73 void Enter() |
|
74 { |
|
75 PR_EnterMonitor(mReentrantMonitor); |
|
76 } |
|
77 |
|
78 /** |
|
79 * Exit |
|
80 * @see prmon.h |
|
81 **/ |
|
82 void Exit() |
|
83 { |
|
84 PR_ExitMonitor(mReentrantMonitor); |
|
85 } |
|
86 |
|
87 /** |
|
88 * Wait |
|
89 * @see prmon.h |
|
90 **/ |
|
91 nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) |
|
92 { |
|
93 #ifdef MOZILLA_INTERNAL_API |
|
94 GeckoProfilerSleepRAII profiler_sleep; |
|
95 #endif //MOZILLA_INTERNAL_API |
|
96 return PR_Wait(mReentrantMonitor, interval) == PR_SUCCESS ? |
|
97 NS_OK : NS_ERROR_FAILURE; |
|
98 } |
|
99 |
|
100 #else // ifndef DEBUG |
|
101 void Enter(); |
|
102 void Exit(); |
|
103 nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT); |
|
104 |
|
105 #endif // ifndef DEBUG |
|
106 |
|
107 /** |
|
108 * Notify |
|
109 * @see prmon.h |
|
110 **/ |
|
111 nsresult Notify() |
|
112 { |
|
113 return PR_Notify(mReentrantMonitor) == PR_SUCCESS |
|
114 ? NS_OK : NS_ERROR_FAILURE; |
|
115 } |
|
116 |
|
117 /** |
|
118 * NotifyAll |
|
119 * @see prmon.h |
|
120 **/ |
|
121 nsresult NotifyAll() |
|
122 { |
|
123 return PR_NotifyAll(mReentrantMonitor) == PR_SUCCESS |
|
124 ? NS_OK : NS_ERROR_FAILURE; |
|
125 } |
|
126 |
|
127 #ifdef DEBUG |
|
128 /** |
|
129 * AssertCurrentThreadIn |
|
130 * @see prmon.h |
|
131 **/ |
|
132 void AssertCurrentThreadIn() |
|
133 { |
|
134 PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor); |
|
135 } |
|
136 |
|
137 /** |
|
138 * AssertNotCurrentThreadIn |
|
139 * @see prmon.h |
|
140 **/ |
|
141 void AssertNotCurrentThreadIn() |
|
142 { |
|
143 // FIXME bug 476536 |
|
144 } |
|
145 |
|
146 #else |
|
147 void AssertCurrentThreadIn() |
|
148 { |
|
149 } |
|
150 void AssertNotCurrentThreadIn() |
|
151 { |
|
152 } |
|
153 |
|
154 #endif // ifdef DEBUG |
|
155 |
|
156 private: |
|
157 ReentrantMonitor(); |
|
158 ReentrantMonitor(const ReentrantMonitor&); |
|
159 ReentrantMonitor& operator =(const ReentrantMonitor&); |
|
160 |
|
161 PRMonitor* mReentrantMonitor; |
|
162 #ifdef DEBUG |
|
163 int32_t mEntryCount; |
|
164 #endif |
|
165 }; |
|
166 |
|
167 |
|
168 /** |
|
169 * ReentrantMonitorAutoEnter |
|
170 * Enters the ReentrantMonitor when it enters scope, and exits it when |
|
171 * it leaves scope. |
|
172 * |
|
173 * MUCH PREFERRED to bare calls to ReentrantMonitor.Enter and Exit. |
|
174 */ |
|
175 class NS_COM_GLUE MOZ_STACK_CLASS ReentrantMonitorAutoEnter |
|
176 { |
|
177 public: |
|
178 /** |
|
179 * Constructor |
|
180 * The constructor aquires the given lock. The destructor |
|
181 * releases the lock. |
|
182 * |
|
183 * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*. |
|
184 **/ |
|
185 ReentrantMonitorAutoEnter(mozilla::ReentrantMonitor &aReentrantMonitor) : |
|
186 mReentrantMonitor(&aReentrantMonitor) |
|
187 { |
|
188 NS_ASSERTION(mReentrantMonitor, "null monitor"); |
|
189 mReentrantMonitor->Enter(); |
|
190 } |
|
191 |
|
192 ~ReentrantMonitorAutoEnter(void) |
|
193 { |
|
194 mReentrantMonitor->Exit(); |
|
195 } |
|
196 |
|
197 nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT) |
|
198 { |
|
199 return mReentrantMonitor->Wait(interval); |
|
200 } |
|
201 |
|
202 nsresult Notify() |
|
203 { |
|
204 return mReentrantMonitor->Notify(); |
|
205 } |
|
206 |
|
207 nsresult NotifyAll() |
|
208 { |
|
209 return mReentrantMonitor->NotifyAll(); |
|
210 } |
|
211 |
|
212 private: |
|
213 ReentrantMonitorAutoEnter(); |
|
214 ReentrantMonitorAutoEnter(const ReentrantMonitorAutoEnter&); |
|
215 ReentrantMonitorAutoEnter& operator =(const ReentrantMonitorAutoEnter&); |
|
216 static void* operator new(size_t) CPP_THROW_NEW; |
|
217 static void operator delete(void*); |
|
218 |
|
219 mozilla::ReentrantMonitor* mReentrantMonitor; |
|
220 }; |
|
221 |
|
222 /** |
|
223 * ReentrantMonitorAutoExit |
|
224 * Exit the ReentrantMonitor when it enters scope, and enters it when it leaves |
|
225 * scope. |
|
226 * |
|
227 * MUCH PREFERRED to bare calls to ReentrantMonitor.Exit and Enter. |
|
228 */ |
|
229 class MOZ_STACK_CLASS ReentrantMonitorAutoExit |
|
230 { |
|
231 public: |
|
232 /** |
|
233 * Constructor |
|
234 * The constructor releases the given lock. The destructor |
|
235 * acquires the lock. The lock must be held before constructing |
|
236 * this object! |
|
237 * |
|
238 * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*. It |
|
239 * must be already locked. |
|
240 **/ |
|
241 ReentrantMonitorAutoExit(ReentrantMonitor& aReentrantMonitor) : |
|
242 mReentrantMonitor(&aReentrantMonitor) |
|
243 { |
|
244 NS_ASSERTION(mReentrantMonitor, "null monitor"); |
|
245 mReentrantMonitor->AssertCurrentThreadIn(); |
|
246 mReentrantMonitor->Exit(); |
|
247 } |
|
248 |
|
249 ~ReentrantMonitorAutoExit(void) |
|
250 { |
|
251 mReentrantMonitor->Enter(); |
|
252 } |
|
253 |
|
254 private: |
|
255 ReentrantMonitorAutoExit(); |
|
256 ReentrantMonitorAutoExit(const ReentrantMonitorAutoExit&); |
|
257 ReentrantMonitorAutoExit& operator =(const ReentrantMonitorAutoExit&); |
|
258 static void* operator new(size_t) CPP_THROW_NEW; |
|
259 static void operator delete(void*); |
|
260 |
|
261 ReentrantMonitor* mReentrantMonitor; |
|
262 }; |
|
263 |
|
264 } // namespace mozilla |
|
265 |
|
266 |
|
267 #endif // ifndef mozilla_ReentrantMonitor_h |