On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / xpcom / glue / nsThreadUtils.h
blob6c09cd7b66bc86bdbe273c0662d46d6c15298895
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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.
16 * The Original Code is Mozilla code.
18 * The Initial Developer of the Original Code is Google Inc.
19 * Portions created by the Initial Developer are Copyright (C) 2006
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Darin Fisher <darin@meer.net>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * 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.
37 * ***** END LICENSE BLOCK ***** */
39 #ifndef nsThreadUtils_h__
40 #define nsThreadUtils_h__
42 #include "prthread.h"
43 #include "prinrval.h"
44 #include "nsIThreadManager.h"
45 #include "nsIThread.h"
46 #include "nsIRunnable.h"
47 #include "nsStringGlue.h"
48 #include "nsCOMPtr.h"
50 // This is needed on some systems to prevent collisions between the symbols
51 // appearing in xpcom_core and xpcomglue. It may be unnecessary in the future
52 // with better toolchain support.
53 #ifdef MOZILLA_INTERNAL_API
54 # define NS_NewThread NS_NewThread_P
55 # define NS_GetCurrentThread NS_GetCurrentThread_P
56 # define NS_GetMainThread NS_GetMainThread_P
57 # define NS_IsMainThread NS_IsMainThread_P
58 # define NS_DispatchToCurrentThread NS_DispatchToCurrentThread_P
59 # define NS_DispatchToMainThread NS_DispatchToMainThread_P
60 # define NS_ProcessPendingEvents NS_ProcessPendingEvents_P
61 # define NS_HasPendingEvents NS_HasPendingEvents_P
62 # define NS_ProcessNextEvent NS_ProcessNextEvent_P
63 #endif
65 //-----------------------------------------------------------------------------
66 // These methods are alternatives to the methods on nsIThreadManager, provided
67 // for convenience.
69 /**
70 * Create a new thread, and optionally provide an initial event for the thread.
72 * @param result
73 * The resulting nsIThread object.
74 * @param initialEvent
75 * The initial event to run on this thread. This parameter may be null.
77 * @returns NS_ERROR_INVALID_ARG
78 * Indicates that the given name is not unique.
80 extern NS_COM_GLUE NS_METHOD
81 NS_NewThread(nsIThread **result, nsIRunnable *initialEvent = nsnull);
83 /**
84 * Get a reference to the current thread.
86 * @param result
87 * The resulting nsIThread object.
89 extern NS_COM_GLUE NS_METHOD
90 NS_GetCurrentThread(nsIThread **result);
92 /**
93 * Get a reference to the main thread.
95 * @param result
96 * The resulting nsIThread object.
98 extern NS_COM_GLUE NS_METHOD
99 NS_GetMainThread(nsIThread **result);
102 * Test to see if the current thread is the main thread.
104 * @returns PR_TRUE if the current thread is the main thread, and PR_FALSE
105 * otherwise.
107 extern NS_COM_GLUE NS_METHOD_(PRBool)
108 NS_IsMainThread();
111 * Dispatch the given event to the current thread.
113 * @param event
114 * The event to dispatch.
116 * @returns NS_ERROR_INVALID_ARG
117 * If event is null.
119 extern NS_COM_GLUE NS_METHOD
120 NS_DispatchToCurrentThread(nsIRunnable *event);
123 * Dispatch the given event to the main thread.
125 * @param event
126 * The event to dispatch.
127 * @param dispatchFlags
128 * The flags to pass to the main thread's dispatch method.
130 * @returns NS_ERROR_INVALID_ARG
131 * If event is null.
133 extern NS_COM_GLUE NS_METHOD
134 NS_DispatchToMainThread(nsIRunnable *event,
135 PRUint32 dispatchFlags = NS_DISPATCH_NORMAL);
137 #ifndef XPCOM_GLUE_AVOID_NSPR
139 * Process all pending events for the given thread before returning. This
140 * method simply calls ProcessNextEvent on the thread while HasPendingEvents
141 * continues to return true and the time spent in NS_ProcessPendingEvents
142 * does not exceed the given timeout value.
144 * @param thread
145 * The thread object for which to process pending events. If null, then
146 * events will be processed for the current thread.
147 * @param timeout
148 * The maximum number of milliseconds to spend processing pending events.
149 * Events are not pre-empted to honor this timeout. Rather, the timeout
150 * value is simply used to determine whether or not to process another event.
151 * Pass PR_INTERVAL_NO_TIMEOUT to specify no timeout.
153 extern NS_COM_GLUE NS_METHOD
154 NS_ProcessPendingEvents(nsIThread *thread,
155 PRIntervalTime timeout = PR_INTERVAL_NO_TIMEOUT);
156 #endif
159 * Shortcut for nsIThread::HasPendingEvents.
161 * It is an error to call this function when the given thread is not the
162 * current thread. This function will return PR_FALSE if called from some
163 * other thread.
165 * @param thread
166 * The current thread or null.
168 * @returns
169 * A boolean value that if "true" indicates that there are pending events
170 * in the current thread's event queue.
172 extern NS_COM_GLUE PRBool
173 NS_HasPendingEvents(nsIThread *thread = nsnull);
176 * Shortcut for nsIThread::ProcessNextEvent.
178 * It is an error to call this function when the given thread is not the
179 * current thread. This function will simply return PR_FALSE if called
180 * from some other thread.
182 * @param thread
183 * The current thread or null.
184 * @param mayWait
185 * A boolean parameter that if "true" indicates that the method may block
186 * the calling thread to wait for a pending event.
188 * @returns
189 * A boolean value that if "true" indicates that an event from the current
190 * thread's event queue was processed.
192 extern NS_COM_GLUE PRBool
193 NS_ProcessNextEvent(nsIThread *thread = nsnull, PRBool mayWait = PR_TRUE);
195 //-----------------------------------------------------------------------------
196 // Helpers that work with nsCOMPtr:
198 inline already_AddRefed<nsIThread>
199 do_GetCurrentThread() {
200 nsIThread *thread = nsnull;
201 NS_GetCurrentThread(&thread);
202 return already_AddRefed<nsIThread>(thread);
205 inline already_AddRefed<nsIThread>
206 do_GetMainThread() {
207 nsIThread *thread = nsnull;
208 NS_GetMainThread(&thread);
209 return already_AddRefed<nsIThread>(thread);
212 //-----------------------------------------------------------------------------
214 #ifdef MOZILLA_INTERNAL_API
215 // Fast access to the current thread. Do not release the returned pointer! If
216 // you want to use this pointer from some other thread, then you will need to
217 // AddRef it. Otherwise, you should only consider this pointer valid from code
218 // running on the current thread.
219 extern NS_COM_GLUE nsIThread *NS_GetCurrentThread();
220 #endif
222 //-----------------------------------------------------------------------------
224 #ifndef XPCOM_GLUE_AVOID_NSPR
226 #undef IMETHOD_VISIBILITY
227 #define IMETHOD_VISIBILITY NS_COM_GLUE
229 // This class is designed to be subclassed.
230 class NS_COM_GLUE nsRunnable : public nsIRunnable
232 public:
233 NS_DECL_ISUPPORTS
234 NS_DECL_NSIRUNNABLE
236 nsRunnable() {
239 protected:
240 virtual ~nsRunnable() {
244 #undef IMETHOD_VISIBILITY
245 #define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN
247 // An event that can be used to call a method on a class. The class type must
248 // support reference counting. This event supports Revoke for use
249 // with nsRevocableEventPtr.
250 template <class T>
251 class nsRunnableMethod : public nsRunnable
253 public:
254 typedef void (T::*Method)();
256 nsRunnableMethod(T *obj, Method method)
257 : mObj(obj), mMethod(method) {
258 NS_ADDREF(mObj);
261 NS_IMETHOD Run() {
262 if (!mObj)
263 return NS_OK;
264 (mObj->*mMethod)();
265 return NS_OK;
268 void Revoke() {
269 NS_IF_RELEASE(mObj);
272 private:
273 virtual ~nsRunnableMethod() {
274 NS_IF_RELEASE(mObj);
277 T *mObj;
278 Method mMethod;
281 // Use this helper macro like so:
283 // nsCOMPtr<nsIRunnable> event =
284 // NS_NEW_RUNNABLE_METHOD(MyClass, myObject, HandleEvent);
285 // NS_DispatchToCurrentThread(event);
287 // Constraints:
288 // - myObject must be of type MyClass
289 // - MyClass must defined AddRef and Release methods
291 // NOTE: Attempts to make this a template function caused VC6 to barf :-(
293 #define NS_NEW_RUNNABLE_METHOD(class_, obj_, method_) \
294 new nsRunnableMethod<class_>(obj_, &class_::method_)
296 #endif // XPCOM_GLUE_AVOID_NSPR
298 // This class is designed to be used when you have an event class E that has a
299 // pointer back to resource class R. If R goes away while E is still pending,
300 // then it is important to "revoke" E so that it does not try use R after R has
301 // been destroyed. nsRevocableEventPtr makes it easy for R to manage such
302 // situations:
304 // class R;
306 // class E : public nsRunnable {
307 // public:
308 // void Revoke() {
309 // mResource = nsnull;
310 // }
311 // private:
312 // R *mResource;
313 // };
315 // class R {
316 // public:
317 // void EventHandled() {
318 // mEvent.Forget();
319 // }
320 // private:
321 // nsRevocableEventPtr<E> mEvent;
322 // };
324 // void R::PostEvent() {
325 // // Make sure any pending event is revoked.
326 // mEvent->Revoke();
328 // nsCOMPtr<nsIRunnable> event = new E();
329 // if (NS_SUCCEEDED(NS_DispatchToCurrentThread(event))) {
330 // // Keep pointer to event so we can revoke it.
331 // mEvent = event;
332 // }
333 // }
335 // NS_IMETHODIMP E::Run() {
336 // if (!mResource)
337 // return NS_OK;
338 // ...
339 // mResource->EventHandled();
340 // return NS_OK;
341 // }
343 template <class T>
344 class nsRevocableEventPtr {
345 public:
346 nsRevocableEventPtr()
347 : mEvent(nsnull) {
350 ~nsRevocableEventPtr() {
351 Revoke();
354 const nsRevocableEventPtr& operator=(T *event) {
355 Revoke();
356 mEvent = event;
357 return *this;
360 void Revoke() {
361 if (mEvent) {
362 mEvent->Revoke();
363 mEvent = nsnull;
367 void Forget() {
368 mEvent = nsnull;
371 PRBool IsPending() {
372 return mEvent != nsnull;
375 T *get() { return mEvent; }
377 private:
378 // Not implemented
379 nsRevocableEventPtr(const nsRevocableEventPtr&);
380 nsRevocableEventPtr& operator=(const nsRevocableEventPtr&);
382 T *mEvent;
385 #endif // nsThreadUtils_h__