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/. */
7 #ifndef mozilla_ReentrantMonitor_h
8 #define mozilla_ReentrantMonitor_h
12 #if defined(MOZILLA_INTERNAL_API) && !defined(DEBUG)
13 # include "GeckoProfiler.h"
14 #endif // defined( MOZILLA_INTERNAL_API) && !defined(DEBUG)
16 #include "mozilla/BlockingResourceBase.h"
17 #include "nsISupports.h"
22 // - ReentrantMonitor, a Java-like monitor
23 // - ReentrantMonitorAutoEnter, an RAII class for ensuring that
24 // ReentrantMonitors are properly entered and exited
26 // Using ReentrantMonitorAutoEnter is MUCH preferred to making bare calls to
27 // ReentrantMonitor.Enter and Exit.
34 * When possible, use ReentrantMonitorAutoEnter to hold this monitor within a
35 * scope, instead of calling Enter/Exit directly.
37 class ReentrantMonitor
: BlockingResourceBase
{
41 * @param aName A name which can reference this monitor
43 explicit ReentrantMonitor(const char* aName
)
44 : BlockingResourceBase(aName
, eReentrantMonitor
)
50 MOZ_COUNT_CTOR(ReentrantMonitor
);
51 mReentrantMonitor
= PR_NewMonitor();
52 if (!mReentrantMonitor
) {
53 MOZ_CRASH("Can't allocate mozilla::ReentrantMonitor");
61 NS_ASSERTION(mReentrantMonitor
,
62 "improperly constructed ReentrantMonitor or double free");
63 PR_DestroyMonitor(mReentrantMonitor
);
64 mReentrantMonitor
= 0;
65 MOZ_COUNT_DTOR(ReentrantMonitor
);
73 void Enter() { PR_EnterMonitor(mReentrantMonitor
); }
79 void Exit() { PR_ExitMonitor(mReentrantMonitor
); }
85 nsresult
Wait(PRIntervalTime aInterval
= PR_INTERVAL_NO_TIMEOUT
) {
86 # ifdef MOZILLA_INTERNAL_API
87 AUTO_PROFILER_THREAD_SLEEP
;
88 # endif // MOZILLA_INTERNAL_API
89 return PR_Wait(mReentrantMonitor
, aInterval
) == PR_SUCCESS
97 nsresult
Wait(PRIntervalTime aInterval
= PR_INTERVAL_NO_TIMEOUT
);
99 #endif // ifndef DEBUG
106 return PR_Notify(mReentrantMonitor
) == PR_SUCCESS
? NS_OK
114 nsresult
NotifyAll() {
115 return PR_NotifyAll(mReentrantMonitor
) == PR_SUCCESS
? NS_OK
121 * AssertCurrentThreadIn
124 void AssertCurrentThreadIn() {
125 PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor
);
129 * AssertNotCurrentThreadIn
132 void AssertNotCurrentThreadIn() {
137 void AssertCurrentThreadIn() {}
138 void AssertNotCurrentThreadIn() {}
140 #endif // ifdef DEBUG
144 ReentrantMonitor(const ReentrantMonitor
&);
145 ReentrantMonitor
& operator=(const ReentrantMonitor
&);
147 PRMonitor
* mReentrantMonitor
;
154 * ReentrantMonitorAutoEnter
155 * Enters the ReentrantMonitor when it enters scope, and exits it when
158 * MUCH PREFERRED to bare calls to ReentrantMonitor.Enter and Exit.
160 class MOZ_STACK_CLASS ReentrantMonitorAutoEnter
{
164 * The constructor aquires the given lock. The destructor
167 * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*.
169 explicit ReentrantMonitorAutoEnter(
170 mozilla::ReentrantMonitor
& aReentrantMonitor
)
171 : mReentrantMonitor(&aReentrantMonitor
) {
172 NS_ASSERTION(mReentrantMonitor
, "null monitor");
173 mReentrantMonitor
->Enter();
176 ~ReentrantMonitorAutoEnter(void) { mReentrantMonitor
->Exit(); }
178 nsresult
Wait(PRIntervalTime aInterval
= PR_INTERVAL_NO_TIMEOUT
) {
179 return mReentrantMonitor
->Wait(aInterval
);
182 nsresult
Notify() { return mReentrantMonitor
->Notify(); }
183 nsresult
NotifyAll() { return mReentrantMonitor
->NotifyAll(); }
186 ReentrantMonitorAutoEnter();
187 ReentrantMonitorAutoEnter(const ReentrantMonitorAutoEnter
&);
188 ReentrantMonitorAutoEnter
& operator=(const ReentrantMonitorAutoEnter
&);
189 static void* operator new(size_t) noexcept(true);
191 friend class ReentrantMonitorAutoExit
;
193 mozilla::ReentrantMonitor
* mReentrantMonitor
;
197 * ReentrantMonitorAutoExit
198 * Exit the ReentrantMonitor when it enters scope, and enters it when it leaves
201 * MUCH PREFERRED to bare calls to ReentrantMonitor.Exit and Enter.
203 class MOZ_STACK_CLASS ReentrantMonitorAutoExit
{
207 * The constructor releases the given lock. The destructor
208 * acquires the lock. The lock must be held before constructing
211 * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*. It
212 * must be already locked.
214 explicit ReentrantMonitorAutoExit(ReentrantMonitor
& aReentrantMonitor
)
215 : mReentrantMonitor(&aReentrantMonitor
) {
216 NS_ASSERTION(mReentrantMonitor
, "null monitor");
217 mReentrantMonitor
->AssertCurrentThreadIn();
218 mReentrantMonitor
->Exit();
221 explicit ReentrantMonitorAutoExit(
222 ReentrantMonitorAutoEnter
& aReentrantMonitorAutoEnter
)
223 : mReentrantMonitor(aReentrantMonitorAutoEnter
.mReentrantMonitor
) {
224 NS_ASSERTION(mReentrantMonitor
, "null monitor");
225 mReentrantMonitor
->AssertCurrentThreadIn();
226 mReentrantMonitor
->Exit();
229 ~ReentrantMonitorAutoExit(void) { mReentrantMonitor
->Enter(); }
232 ReentrantMonitorAutoExit();
233 ReentrantMonitorAutoExit(const ReentrantMonitorAutoExit
&);
234 ReentrantMonitorAutoExit
& operator=(const ReentrantMonitorAutoExit
&);
235 static void* operator new(size_t) noexcept(true);
237 ReentrantMonitor
* mReentrantMonitor
;
240 } // namespace mozilla
242 #endif // ifndef mozilla_ReentrantMonitor_h