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
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.
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__
44 #include "nsIThreadManager.h"
45 #include "nsIThread.h"
46 #include "nsIRunnable.h"
47 #include "nsStringGlue.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
65 //-----------------------------------------------------------------------------
66 // These methods are alternatives to the methods on nsIThreadManager, provided
70 * Create a new thread, and optionally provide an initial event for the thread.
73 * The resulting nsIThread object.
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
);
84 * Get a reference to the current thread.
87 * The resulting nsIThread object.
89 extern NS_COM_GLUE NS_METHOD
90 NS_GetCurrentThread(nsIThread
**result
);
93 * Get a reference to the main thread.
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
107 extern NS_COM_GLUE
NS_METHOD_(PRBool
)
111 * Dispatch the given event to the current thread.
114 * The event to dispatch.
116 * @returns NS_ERROR_INVALID_ARG
119 extern NS_COM_GLUE NS_METHOD
120 NS_DispatchToCurrentThread(nsIRunnable
*event
);
123 * Dispatch the given event to the main thread.
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
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.
145 * The thread object for which to process pending events. If null, then
146 * events will be processed for the current thread.
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
);
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
166 * The current thread or null.
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.
183 * The current thread or null.
185 * A boolean parameter that if "true" indicates that the method may block
186 * the calling thread to wait for a pending event.
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
>
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();
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
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.
251 class nsRunnableMethod
: public nsRunnable
254 typedef void (T::*Method
)();
256 nsRunnableMethod(T
*obj
, Method method
)
257 : mObj(obj
), mMethod(method
) {
273 virtual ~nsRunnableMethod() {
281 // Use this helper macro like so:
283 // nsCOMPtr<nsIRunnable> event =
284 // NS_NEW_RUNNABLE_METHOD(MyClass, myObject, HandleEvent);
285 // NS_DispatchToCurrentThread(event);
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
306 // class E : public nsRunnable {
309 // mResource = nsnull;
317 // void EventHandled() {
321 // nsRevocableEventPtr<E> mEvent;
324 // void R::PostEvent() {
325 // // Make sure any pending event is revoked.
328 // nsCOMPtr<nsIRunnable> event = new E();
329 // if (NS_SUCCEEDED(NS_DispatchToCurrentThread(event))) {
330 // // Keep pointer to event so we can revoke it.
335 // NS_IMETHODIMP E::Run() {
339 // mResource->EventHandled();
344 class nsRevocableEventPtr
{
346 nsRevocableEventPtr()
350 ~nsRevocableEventPtr() {
354 const nsRevocableEventPtr
& operator=(T
*event
) {
372 return mEvent
!= nsnull
;
375 T
*get() { return mEvent
; }
379 nsRevocableEventPtr(const nsRevocableEventPtr
&);
380 nsRevocableEventPtr
& operator=(const nsRevocableEventPtr
&);
385 #endif // nsThreadUtils_h__