1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: sw=4 ts=4 et :
3 : * ***** BEGIN LICENSE BLOCK *****
4 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 : *
6 : * The contents of this file are subject to the Mozilla Public License Version
7 : * 1.1 (the "License"); you may not use this file except in compliance with
8 : * the License. You may obtain a copy of the License at
9 : * http://www.mozilla.org/MPL/
10 : *
11 : * Software distributed under the License is distributed on an "AS IS" basis,
12 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 : * for the specific language governing rights and limitations under the
14 : * License.
15 : *
16 : * The Original Code is mozilla.org code.
17 : *
18 : * The Initial Developer of the Original Code is
19 : * Netscape Communications Corporation.
20 : * Portions created by the Initial Developer are Copyright (C) 1998
21 : * the Initial Developer. All Rights Reserved.
22 : *
23 : * Contributor(s):
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either of the GNU General Public License Version 2 or later (the "GPL"),
27 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef mozilla_ReentrantMonitor_h
40 : #define mozilla_ReentrantMonitor_h
41 :
42 : #include "prmon.h"
43 :
44 : #include "mozilla/BlockingResourceBase.h"
45 :
46 : //
47 : // Provides:
48 : //
49 : // - ReentrantMonitor, a Java-like monitor
50 : // - ReentrantMonitorAutoEnter, an RAII class for ensuring that
51 : // ReentrantMonitors are properly entered and exited
52 : //
53 : // Using ReentrantMonitorAutoEnter is MUCH preferred to making bare calls to
54 : // ReentrantMonitor.Enter and Exit.
55 : //
56 : namespace mozilla {
57 :
58 :
59 : /**
60 : * ReentrantMonitor
61 : * Java-like monitor.
62 : * When possible, use ReentrantMonitorAutoEnter to hold this monitor within a
63 : * scope, instead of calling Enter/Exit directly.
64 : **/
65 : class NS_COM_GLUE ReentrantMonitor : BlockingResourceBase
66 : {
67 : public:
68 : /**
69 : * ReentrantMonitor
70 : * @param aName A name which can reference this monitor
71 : */
72 44557 : ReentrantMonitor(const char* aName) :
73 : BlockingResourceBase(aName, eReentrantMonitor)
74 : #ifdef DEBUG
75 44557 : , mEntryCount(0)
76 : #endif
77 : {
78 44557 : MOZ_COUNT_CTOR(ReentrantMonitor);
79 44557 : mReentrantMonitor = PR_NewMonitor();
80 44557 : if (!mReentrantMonitor)
81 0 : NS_RUNTIMEABORT("Can't allocate mozilla::ReentrantMonitor");
82 44557 : }
83 :
84 : /**
85 : * ~ReentrantMonitor
86 : **/
87 44507 : ~ReentrantMonitor()
88 44507 : {
89 44507 : NS_ASSERTION(mReentrantMonitor,
90 : "improperly constructed ReentrantMonitor or double free");
91 44507 : PR_DestroyMonitor(mReentrantMonitor);
92 44507 : mReentrantMonitor = 0;
93 44507 : MOZ_COUNT_DTOR(ReentrantMonitor);
94 44507 : }
95 :
96 : #ifndef DEBUG
97 : /**
98 : * Enter
99 : * @see prmon.h
100 : **/
101 : void Enter()
102 : {
103 : PR_EnterMonitor(mReentrantMonitor);
104 : }
105 :
106 : /**
107 : * Exit
108 : * @see prmon.h
109 : **/
110 : void Exit()
111 : {
112 : PR_ExitMonitor(mReentrantMonitor);
113 : }
114 :
115 : /**
116 : * Wait
117 : * @see prmon.h
118 : **/
119 : nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT)
120 : {
121 : return PR_Wait(mReentrantMonitor, interval) == PR_SUCCESS ?
122 : NS_OK : NS_ERROR_FAILURE;
123 : }
124 :
125 : #else
126 : void Enter();
127 : void Exit();
128 : nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT);
129 :
130 : #endif // ifndef DEBUG
131 :
132 : /**
133 : * Notify
134 : * @see prmon.h
135 : **/
136 6794 : nsresult Notify()
137 : {
138 6794 : return PR_Notify(mReentrantMonitor) == PR_SUCCESS
139 6794 : ? NS_OK : NS_ERROR_FAILURE;
140 : }
141 :
142 : /**
143 : * NotifyAll
144 : * @see prmon.h
145 : **/
146 316411 : nsresult NotifyAll()
147 : {
148 316411 : return PR_NotifyAll(mReentrantMonitor) == PR_SUCCESS
149 316410 : ? NS_OK : NS_ERROR_FAILURE;
150 : }
151 :
152 : #ifdef DEBUG
153 : /**
154 : * AssertCurrentThreadIn
155 : * @see prmon.h
156 : **/
157 5062676 : void AssertCurrentThreadIn()
158 : {
159 5062676 : PR_ASSERT_CURRENT_THREAD_IN_MONITOR(mReentrantMonitor);
160 5062676 : }
161 :
162 : /**
163 : * AssertNotCurrentThreadIn
164 : * @see prmon.h
165 : **/
166 0 : void AssertNotCurrentThreadIn()
167 : {
168 : // FIXME bug 476536
169 0 : }
170 :
171 : #else
172 : void AssertCurrentThreadIn()
173 : {
174 : }
175 : void AssertNotCurrentThreadIn()
176 : {
177 : }
178 :
179 : #endif // ifdef DEBUG
180 :
181 : private:
182 : ReentrantMonitor();
183 : ReentrantMonitor(const ReentrantMonitor&);
184 : ReentrantMonitor& operator =(const ReentrantMonitor&);
185 :
186 : PRMonitor* mReentrantMonitor;
187 : #ifdef DEBUG
188 : PRInt32 mEntryCount;
189 : #endif
190 : };
191 :
192 :
193 : /**
194 : * ReentrantMonitorAutoEnter
195 : * Enters the ReentrantMonitor when it enters scope, and exits it when
196 : * it leaves scope.
197 : *
198 : * MUCH PREFERRED to bare calls to ReentrantMonitor.Enter and Exit.
199 : */
200 : class NS_COM_GLUE NS_STACK_CLASS ReentrantMonitorAutoEnter
201 : {
202 : public:
203 : /**
204 : * Constructor
205 : * The constructor aquires the given lock. The destructor
206 : * releases the lock.
207 : *
208 : * @param aReentrantMonitor A valid mozilla::ReentrantMonitor*.
209 : **/
210 4114626 : ReentrantMonitorAutoEnter(mozilla::ReentrantMonitor &aReentrantMonitor) :
211 4114626 : mReentrantMonitor(&aReentrantMonitor)
212 : {
213 4114626 : NS_ASSERTION(mReentrantMonitor, "null monitor");
214 4114626 : mReentrantMonitor->Enter();
215 4114595 : }
216 :
217 4114631 : ~ReentrantMonitorAutoEnter(void)
218 : {
219 4114631 : mReentrantMonitor->Exit();
220 4114616 : }
221 :
222 68033 : nsresult Wait(PRIntervalTime interval = PR_INTERVAL_NO_TIMEOUT)
223 : {
224 68033 : return mReentrantMonitor->Wait(interval);
225 : }
226 :
227 6788 : nsresult Notify()
228 : {
229 6788 : return mReentrantMonitor->Notify();
230 : }
231 :
232 301683 : nsresult NotifyAll()
233 : {
234 301683 : return mReentrantMonitor->NotifyAll();
235 : }
236 :
237 : private:
238 : ReentrantMonitorAutoEnter();
239 : ReentrantMonitorAutoEnter(const ReentrantMonitorAutoEnter&);
240 : ReentrantMonitorAutoEnter& operator =(const ReentrantMonitorAutoEnter&);
241 : static void* operator new(size_t) CPP_THROW_NEW;
242 : static void operator delete(void*);
243 :
244 : mozilla::ReentrantMonitor* mReentrantMonitor;
245 : };
246 :
247 :
248 : } // namespace mozilla
249 :
250 :
251 : #endif // ifndef mozilla_ReentrantMonitor_h
|