Bug 1893155 - Part 1: Make Calendar{WeekOfYear,YearOfWeek} return undefined. r=spider...
[gecko.git] / xpcom / threads / ReentrantMonitor.h
blob09debad57753f0d89b0693baf626e118da1bd61b
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 "mozilla/ProfilerThreadSleep.h"
14 #endif // defined( MOZILLA_INTERNAL_API) && !defined(DEBUG)
16 #include "mozilla/BlockingResourceBase.h"
17 #include "mozilla/ThreadSafety.h"
18 #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 MOZ_CAPABILITY("reentrant monitor") ReentrantMonitor
38 : BlockingResourceBase {
39 public:
40 /**
41 * ReentrantMonitor
42 * @param aName A name which can reference this monitor
44 explicit ReentrantMonitor(const char* aName)
45 : BlockingResourceBase(aName, eReentrantMonitor)
46 #ifdef DEBUG
48 mEntryCount(0)
49 #endif
51 MOZ_COUNT_CTOR(ReentrantMonitor);
52 mReentrantMonitor = PR_NewMonitor();
53 if (!mReentrantMonitor) {
54 MOZ_CRASH("Can't allocate mozilla::ReentrantMonitor");
58 /**
59 * ~ReentrantMonitor
60 **/
61 ~ReentrantMonitor() {
62 NS_ASSERTION(mReentrantMonitor,
63 "improperly constructed ReentrantMonitor or double free");
64 PR_DestroyMonitor(mReentrantMonitor);
65 mReentrantMonitor = 0;
66 MOZ_COUNT_DTOR(ReentrantMonitor);
69 #ifndef DEBUG
70 /**
71 * Enter
72 * @see prmon.h
73 **/
74 void Enter() MOZ_CAPABILITY_ACQUIRE() { PR_EnterMonitor(mReentrantMonitor); }
76 /**
77 * Exit
78 * @see prmon.h
79 **/
80 void Exit() MOZ_CAPABILITY_RELEASE() { PR_ExitMonitor(mReentrantMonitor); }
82 /**
83 * Wait
84 * @see prmon.h
85 **/
86 nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT) {
87 PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor);
88 # ifdef MOZILLA_INTERNAL_API
89 AUTO_PROFILER_THREAD_SLEEP;
90 # endif // MOZILLA_INTERNAL_API
91 return PR_Wait(mReentrantMonitor, aInterval) == PR_SUCCESS
92 ? NS_OK
93 : NS_ERROR_FAILURE;
96 #else // ifndef DEBUG
97 void Enter() MOZ_CAPABILITY_ACQUIRE();
98 void Exit() MOZ_CAPABILITY_RELEASE();
99 nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT);
101 #endif // ifndef DEBUG
104 * Notify
105 * @see prmon.h
107 nsresult Notify() {
108 return PR_Notify(mReentrantMonitor) == PR_SUCCESS ? NS_OK
109 : NS_ERROR_FAILURE;
113 * NotifyAll
114 * @see prmon.h
116 nsresult NotifyAll() {
117 return PR_NotifyAll(mReentrantMonitor) == PR_SUCCESS ? NS_OK
118 : NS_ERROR_FAILURE;
121 #ifdef DEBUG
123 * AssertCurrentThreadIn
124 * @see prmon.h
126 void AssertCurrentThreadIn() MOZ_ASSERT_CAPABILITY(this) {
127 PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor);
131 * AssertNotCurrentThreadIn
132 * @see prmon.h
134 void AssertNotCurrentThreadIn() MOZ_ASSERT_CAPABILITY(!this) {
135 // FIXME bug 476536
138 #else
139 void AssertCurrentThreadIn() MOZ_ASSERT_CAPABILITY(this) {}
140 void AssertNotCurrentThreadIn() MOZ_ASSERT_CAPABILITY(!this) {}
142 #endif // ifdef DEBUG
144 private:
145 ReentrantMonitor();
146 ReentrantMonitor(const ReentrantMonitor&);
147 ReentrantMonitor& operator=(const ReentrantMonitor&);
149 PRMonitor* mReentrantMonitor;
150 #ifdef DEBUG
151 int32_t mEntryCount;
152 #endif
156 * ReentrantMonitorAutoEnter
157 * Enters the ReentrantMonitor when it enters scope, and exits it when
158 * it leaves scope.
160 * MUCH PREFERRED to bare calls to ReentrantMonitor.Enter and Exit.
162 class MOZ_SCOPED_CAPABILITY MOZ_STACK_CLASS ReentrantMonitorAutoEnter {
163 public:
165 * Constructor
166 * The constructor aquires the given lock. The destructor
167 * releases the lock.
169 * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*.
171 explicit ReentrantMonitorAutoEnter(
172 mozilla::ReentrantMonitor& aReentrantMonitor)
173 MOZ_CAPABILITY_ACQUIRE(aReentrantMonitor)
174 : mReentrantMonitor(&aReentrantMonitor) {
175 NS_ASSERTION(mReentrantMonitor, "null monitor");
176 mReentrantMonitor->Enter();
179 ~ReentrantMonitorAutoEnter(void) MOZ_CAPABILITY_RELEASE() {
180 mReentrantMonitor->Exit();
183 nsresult Wait(PRIntervalTime aInterval = PR_INTERVAL_NO_TIMEOUT) {
184 return mReentrantMonitor->Wait(aInterval);
187 nsresult Notify() { return mReentrantMonitor->Notify(); }
188 nsresult NotifyAll() { return mReentrantMonitor->NotifyAll(); }
190 private:
191 ReentrantMonitorAutoEnter();
192 ReentrantMonitorAutoEnter(const ReentrantMonitorAutoEnter&);
193 ReentrantMonitorAutoEnter& operator=(const ReentrantMonitorAutoEnter&);
194 static void* operator new(size_t) noexcept(true);
196 friend class ReentrantMonitorAutoExit;
198 mozilla::ReentrantMonitor* mReentrantMonitor;
202 * ReentrantMonitorAutoExit
203 * Exit the ReentrantMonitor when it enters scope, and enters it when it leaves
204 * scope.
206 * MUCH PREFERRED to bare calls to ReentrantMonitor.Exit and Enter.
208 class MOZ_SCOPED_CAPABILITY MOZ_STACK_CLASS ReentrantMonitorAutoExit {
209 public:
211 * Constructor
212 * The constructor releases the given lock. The destructor
213 * acquires the lock. The lock must be held before constructing
214 * this object!
216 * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*. It
217 * must be already locked.
219 explicit ReentrantMonitorAutoExit(ReentrantMonitor& aReentrantMonitor)
220 MOZ_EXCLUSIVE_RELEASE(aReentrantMonitor)
221 : mReentrantMonitor(&aReentrantMonitor) {
222 NS_ASSERTION(mReentrantMonitor, "null monitor");
223 mReentrantMonitor->AssertCurrentThreadIn();
224 mReentrantMonitor->Exit();
227 explicit ReentrantMonitorAutoExit(
228 ReentrantMonitorAutoEnter& aReentrantMonitorAutoEnter)
229 MOZ_EXCLUSIVE_RELEASE(aReentrantMonitorAutoEnter.mReentrantMonitor)
230 : mReentrantMonitor(aReentrantMonitorAutoEnter.mReentrantMonitor) {
231 NS_ASSERTION(mReentrantMonitor, "null monitor");
232 mReentrantMonitor->AssertCurrentThreadIn();
233 mReentrantMonitor->Exit();
236 ~ReentrantMonitorAutoExit(void) MOZ_EXCLUSIVE_RELEASE() {
237 mReentrantMonitor->Enter();
240 private:
241 ReentrantMonitorAutoExit();
242 ReentrantMonitorAutoExit(const ReentrantMonitorAutoExit&);
243 ReentrantMonitorAutoExit& operator=(const ReentrantMonitorAutoExit&);
244 static void* operator new(size_t) noexcept(true);
246 ReentrantMonitor* mReentrantMonitor;
249 } // namespace mozilla
251 #endif // ifndef mozilla_ReentrantMonitor_h