Bug 1693453 [wpt PR 27671] - Add test to check the unavailability of storages in...
[gecko.git] / xpcom / threads / ReentrantMonitor.h
blobd1d1145d1b5aa61389a754c559b41816cd2e0fea
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
10 #include "prmon.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"
20 // Provides:
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.
29 namespace mozilla {
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 public:
39 /**
40 * ReentrantMonitor
41 * @param aName A name which can reference this monitor
43 explicit ReentrantMonitor(const char* aName)
44 : BlockingResourceBase(aName, eReentrantMonitor)
45 #ifdef DEBUG
47 mEntryCount(0)
48 #endif
50 MOZ_COUNT_CTOR(ReentrantMonitor);
51 mReentrantMonitor = PR_NewMonitor();
52 if (!mReentrantMonitor) {
53 MOZ_CRASH("Can't allocate mozilla::ReentrantMonitor");
57 /**
58 * ~ReentrantMonitor
59 **/
60 ~ReentrantMonitor() {
61 NS_ASSERTION(mReentrantMonitor,
62 "improperly constructed ReentrantMonitor or double free");
63 PR_DestroyMonitor(mReentrantMonitor);
64 mReentrantMonitor = 0;
65 MOZ_COUNT_DTOR(ReentrantMonitor);
68 #ifndef DEBUG
69 /**
70 * Enter
71 * @see prmon.h
72 **/
73 void Enter() { PR_EnterMonitor(mReentrantMonitor); }
75 /**
76 * Exit
77 * @see prmon.h
78 **/
79 void Exit() { PR_ExitMonitor(mReentrantMonitor); }
81 /**
82 * Wait
83 * @see prmon.h
84 **/
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
90 ? NS_OK
91 : NS_ERROR_FAILURE;
94 #else // ifndef DEBUG
95 void Enter();
96 void Exit();
97 nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT);
99 #endif // ifndef DEBUG
102 * Notify
103 * @see prmon.h
105 nsresult Notify() {
106 return PR_Notify(mReentrantMonitor) == PR_SUCCESS ? NS_OK
107 : NS_ERROR_FAILURE;
111 * NotifyAll
112 * @see prmon.h
114 nsresult NotifyAll() {
115 return PR_NotifyAll(mReentrantMonitor) == PR_SUCCESS ? NS_OK
116 : NS_ERROR_FAILURE;
119 #ifdef DEBUG
121 * AssertCurrentThreadIn
122 * @see prmon.h
124 void AssertCurrentThreadIn() {
125 PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor);
129 * AssertNotCurrentThreadIn
130 * @see prmon.h
132 void AssertNotCurrentThreadIn() {
133 // FIXME bug 476536
136 #else
137 void AssertCurrentThreadIn() {}
138 void AssertNotCurrentThreadIn() {}
140 #endif // ifdef DEBUG
142 private:
143 ReentrantMonitor();
144 ReentrantMonitor(const ReentrantMonitor&);
145 ReentrantMonitor& operator=(const ReentrantMonitor&);
147 PRMonitor* mReentrantMonitor;
148 #ifdef DEBUG
149 int32_t mEntryCount;
150 #endif
154 * ReentrantMonitorAutoEnter
155 * Enters the ReentrantMonitor when it enters scope, and exits it when
156 * it leaves scope.
158 * MUCH PREFERRED to bare calls to ReentrantMonitor.Enter and Exit.
160 class MOZ_STACK_CLASS ReentrantMonitorAutoEnter {
161 public:
163 * Constructor
164 * The constructor aquires the given lock. The destructor
165 * releases the lock.
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(); }
185 private:
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
199 * scope.
201 * MUCH PREFERRED to bare calls to ReentrantMonitor.Exit and Enter.
203 class MOZ_STACK_CLASS ReentrantMonitorAutoExit {
204 public:
206 * Constructor
207 * The constructor releases the given lock. The destructor
208 * acquires the lock. The lock must be held before constructing
209 * this object!
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(); }
231 private:
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