VirtualBox

source: vbox/trunk/src/libs/xpcom18a4/xpcom/threads/nsAutoLock.h@ 106112

Last change on this file since 106112 was 102470, checked in by vboxsync, 11 months ago

libs/xpcom: Convert the PR_Wait() function to take the timeout in milliseconds and get rid of PR_Interval* and use RTTime*, bugref:10545 [2nd attempt]

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 10.0 KB
Line 
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 *
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
9 *
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
14 *
15 * The Original Code is mozilla.org code.
16 *
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
21 *
22 * Contributor(s):
23 *
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
35 *
36 * ***** END LICENSE BLOCK ***** */
37
38
39/*
40 A stack-based lock object that makes using PRLock a bit more
41 convenient. It acquires the monitor when constructed, and releases
42 it when it goes out of scope.
43
44 For example,
45
46 class Foo {
47 private:
48 PRLock* mLock;
49
50 public:
51 Foo(void) {
52 mLock = PR_NewLock();
53 }
54
55 ~Foo(void) {
56 PR_DestroyLock(mLock);
57 }
58
59 void ThreadSafeMethod(void) {
60 // we're don't hold the lock yet...
61
62 nsAutoLock lock(mLock);
63 // ...but now we do.
64
65 // we even can do wacky stuff like return from arbitrary places w/o
66 // worrying about forgetting to release the lock
67 if (some_weird_condition)
68 return;
69
70 // otherwise do some other stuff
71 }
72
73 void ThreadSafeBlockScope(void) {
74 // we're not in the lock here...
75
76 {
77 nsAutoLock lock(mLock);
78 // but we are now, at least until the block scope closes
79 }
80
81 // ...now we're not in the lock anymore
82 }
83 };
84
85 A similar stack-based locking object is available for PRMonitor. The
86 major difference is that the PRMonitor must be created and destroyed
87 via the static methods on nsAutoMonitor.
88
89 For example:
90 Foo::Foo() {
91 mMon = nsAutoMonitor::NewMonitor("FooMonitor");
92 }
93 nsresult Foo::MyMethod(...) {
94 nsAutoMonitor mon(mMon);
95 ...
96 // go ahead and do deeply nested returns...
97 return NS_ERROR_FAILURE;
98 ...
99 // or call Wait or Notify...
100 mon.Wait();
101 ...
102 // cleanup is automatic
103 }
104 */
105
106#ifndef nsAutoLock_h__
107#define nsAutoLock_h__
108
109#include "nscore.h"
110
111#include <iprt/assert.h>
112#include <iprt/errcore.h>
113#include <iprt/semaphore.h>
114
115/**
116 * nsAutoLockBase
117 * This is the base class for the stack-based locking objects.
118 * Clients of derived classes need not play with this superclass.
119 **/
120class NS_COM nsAutoLockBase {
121protected:
122 nsAutoLockBase() {}
123 enum nsAutoLockType {eAutoLock, eAutoMonitor, eAutoCMonitor};
124
125 nsAutoLockBase(void* addr, nsAutoLockType type) {}
126 ~nsAutoLockBase() {}
127};
128
129/**
130 * nsAutoLock
131 * Stack-based locking object for PRLock.
132 **/
133class NS_COM nsAutoLock : public nsAutoLockBase {
134private:
135 /** The IPRT fast mutex. */
136 RTSEMFASTMUTEX m_hMtx;
137 bool m_fLocked;
138
139 // Not meant to be implemented. This makes it a compiler error to
140 // construct or assign an nsAutoLock object incorrectly.
141 nsAutoLock(void);
142 nsAutoLock(const nsAutoLock& /*aLock*/);
143 nsAutoLock& operator =(const nsAutoLock& /*aLock*/);
144
145 // Not meant to be implemented. This makes it a compiler error to
146 // attempt to create an nsAutoLock object on the heap.
147 static void* operator new(size_t /*size*/) CPP_THROW_NEW;
148 static void operator delete(void* /*memory*/);
149
150public:
151 /**
152 * Constructor
153 * The constructor aquires the given lock. The destructor
154 * releases the lock.
155 *
156 * @param hMtx A valid IPRT fast mutex.
157 **/
158 nsAutoLock(RTSEMFASTMUTEX hMtx)
159 : nsAutoLockBase(hMtx, eAutoLock),
160 m_hMtx(hMtx),
161 m_fLocked(true) {
162 Assert(hMtx != NIL_RTSEMFASTMUTEX);
163 RTSemFastMutexRequest(m_hMtx);
164 }
165
166 ~nsAutoLock(void) {
167 if (m_fLocked)
168 RTSemFastMutexRelease(m_hMtx);
169 }
170
171 /**
172 * lock
173 * Client may call this to reaquire the given lock. Take special
174 * note that attempting to aquire a locked lock will hang or crash.
175 **/
176 void lock() {
177 Assert(!m_fLocked);
178 Assert(m_hMtx != NIL_RTSEMFASTMUTEX);
179 RTSemFastMutexRequest(m_hMtx);
180 m_fLocked = true;
181 }
182
183
184 /**
185 * unlock
186 * Client may call this to release the given lock. Take special
187 * note unlocking an unlocked lock has undefined results.
188 **/
189 void unlock() {
190 Assert(m_fLocked);
191 Assert(m_hMtx != NIL_RTSEMFASTMUTEX);
192 RTSemFastMutexRelease(m_hMtx);
193 m_fLocked = false;
194 }
195};
196
197#include "prmon.h"
198#include "nsError.h"
199
200class NS_COM nsAutoMonitor : public nsAutoLockBase {
201public:
202
203 /**
204 * NewMonitor
205 * Allocates a new PRMonitor for use with nsAutoMonitor.
206 * @param name A (unique /be?) name which can reference this monitor
207 * @returns nsnull if failure
208 * A valid PRMonitor* is successful while must be destroyed
209 * by nsAutoMonitor::DestroyMonitor()
210 **/
211 static PRMonitor* NewMonitor(const char* name);
212 static void DestroyMonitor(PRMonitor* mon);
213
214
215 /**
216 * Constructor
217 * The constructor locks the given monitor. During destruction
218 * the monitor will be unlocked.
219 *
220 * @param mon A valid PRMonitor* returned from
221 * nsAutoMonitor::NewMonitor().
222 **/
223 nsAutoMonitor(PRMonitor* mon)
224 : nsAutoLockBase((void*)mon, eAutoMonitor),
225 mMonitor(mon), mLockCount(0)
226 {
227 AssertMsg(mMonitor, ("null monitor"));
228 if (mMonitor) {
229 PR_EnterMonitor(mMonitor);
230 mLockCount = 1;
231 }
232 }
233
234 ~nsAutoMonitor() {
235 AssertMsg(mMonitor, ("null monitor"));
236 if (mMonitor && mLockCount) {
237 PR_ExitMonitor(mMonitor);
238 }
239 }
240
241 /**
242 * Enter
243 * Client may call this to reenter the given monitor.
244 * @see prmon.h
245 **/
246 void Enter();
247
248 /**
249 * Exit
250 * Client may call this to exit the given monitor.
251 * @see prmon.h
252 **/
253 void Exit();
254
255 /**
256 * Wait
257 * @see prmon.h
258 **/
259 nsresult Wait(RTMSINTERVAL msTimeout = RT_INDEFINITE_WAIT) {
260 return PR_Wait(mMonitor, msTimeout) == PR_SUCCESS
261 ? NS_OK : NS_ERROR_FAILURE;
262 }
263
264 /**
265 * Notify
266 * @see prmon.h
267 **/
268 nsresult Notify() {
269 return PR_Notify(mMonitor) == PR_SUCCESS
270 ? NS_OK : NS_ERROR_FAILURE;
271 }
272
273 /**
274 * NotifyAll
275 * @see prmon.h
276 **/
277 nsresult NotifyAll() {
278 return PR_NotifyAll(mMonitor) == PR_SUCCESS
279 ? NS_OK : NS_ERROR_FAILURE;
280 }
281
282private:
283 PRMonitor* mMonitor;
284 PRInt32 mLockCount;
285
286 // Not meant to be implemented. This makes it a compiler error to
287 // construct or assign an nsAutoLock object incorrectly.
288 nsAutoMonitor(void);
289 nsAutoMonitor(const nsAutoMonitor& /*aMon*/);
290 nsAutoMonitor& operator =(const nsAutoMonitor& /*aMon*/);
291
292 // Not meant to be implemented. This makes it a compiler error to
293 // attempt to create an nsAutoLock object on the heap.
294 static void* operator new(size_t /*size*/) CPP_THROW_NEW;
295 static void operator delete(void* /*memory*/);
296};
297
298
299/**
300 * Cut down version of the nsAutoMonitor where the passed monitor can be NULL.
301 * Used in exactly one place because the regular nsAutoMonitor would assert in that place
302 * during shutdown (see nsComponentManager::NS_GetServiceManager for an explanation while
303 * the assertion is nothing to orry about actually).
304 */
305class NS_COM nsAutoMonitorCanBeNull : public nsAutoLockBase {
306public:
307
308
309 /**
310 * Constructor
311 * The constructor locks the given monitor. During destruction
312 * the monitor will be unlocked.
313 *
314 * @param mon A valid PRMonitor* returned from
315 * nsAutoMonitor::NewMonitor().
316 **/
317 nsAutoMonitorCanBeNull(PRMonitor* mon)
318 : nsAutoLockBase((void*)mon, eAutoMonitor),
319 mMonitor(mon), mLockCount(0)
320 {
321 if (mMonitor) {
322 PR_EnterMonitor(mMonitor);
323 mLockCount = 1;
324 }
325 }
326
327 ~nsAutoMonitorCanBeNull() {
328 if (mMonitor && mLockCount) {
329 PR_ExitMonitor(mMonitor);
330 }
331 }
332
333private:
334 PRMonitor* mMonitor;
335 PRInt32 mLockCount;
336
337 // Not meant to be implemented. This makes it a compiler error to
338 // construct or assign an nsAutoLock object incorrectly.
339 nsAutoMonitorCanBeNull(void);
340 nsAutoMonitorCanBeNull(const nsAutoMonitorCanBeNull& /*aMon*/);
341 nsAutoMonitorCanBeNull& operator =(const nsAutoMonitorCanBeNull& /*aMon*/);
342
343 // Not meant to be implemented. This makes it a compiler error to
344 // attempt to create an nsAutoLock object on the heap.
345 static void* operator new(size_t /*size*/) CPP_THROW_NEW;
346 static void operator delete(void* /*memory*/);
347};
348
349#endif // nsAutoLock_h__
350
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette