Merge tracemonkey and mozilla-central. (a=blockers)
[mozilla-central.git] / xpcom / glue / nsThreadUtils.cpp
blob1e82e004a396d914c435ea6a71df8904c90bf6da
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 #include "nsThreadUtils.h"
41 #ifdef MOZILLA_INTERNAL_API
42 # include "nsThreadManager.h"
43 #else
44 # include "nsXPCOMCIDInternal.h"
45 # include "nsIThreadManager.h"
46 # include "nsServiceManagerUtils.h"
47 #endif
49 #ifdef XP_WIN
50 #include <windows.h>
51 #endif
53 #ifndef XPCOM_GLUE_AVOID_NSPR
55 NS_IMPL_THREADSAFE_ISUPPORTS1(nsRunnable, nsIRunnable)
57 NS_IMETHODIMP
58 nsRunnable::Run()
60 // Do nothing
61 return NS_OK;
64 #endif // XPCOM_GLUE_AVOID_NSPR
66 //-----------------------------------------------------------------------------
68 NS_METHOD
69 NS_NewThread(nsIThread **result, nsIRunnable *event)
71 nsCOMPtr<nsIThread> thread;
72 #ifdef MOZILLA_INTERNAL_API
73 nsresult rv = nsThreadManager::get()->
74 nsThreadManager::NewThread(0, getter_AddRefs(thread));
75 #else
76 nsresult rv;
77 nsCOMPtr<nsIThreadManager> mgr =
78 do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
79 NS_ENSURE_SUCCESS(rv, rv);
81 rv = mgr->NewThread(0, getter_AddRefs(thread));
82 #endif
83 NS_ENSURE_SUCCESS(rv, rv);
85 if (event) {
86 rv = thread->Dispatch(event, NS_DISPATCH_NORMAL);
87 NS_ENSURE_SUCCESS(rv, rv);
90 *result = nsnull;
91 thread.swap(*result);
92 return NS_OK;
95 NS_METHOD
96 NS_GetCurrentThread(nsIThread **result)
98 #ifdef MOZILLA_INTERNAL_API
99 return nsThreadManager::get()->nsThreadManager::GetCurrentThread(result);
100 #else
101 nsresult rv;
102 nsCOMPtr<nsIThreadManager> mgr =
103 do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
104 NS_ENSURE_SUCCESS(rv, rv);
105 return mgr->GetCurrentThread(result);
106 #endif
109 NS_METHOD
110 NS_GetMainThread(nsIThread **result)
112 #ifdef MOZILLA_INTERNAL_API
113 return nsThreadManager::get()->nsThreadManager::GetMainThread(result);
114 #else
115 nsresult rv;
116 nsCOMPtr<nsIThreadManager> mgr =
117 do_GetService(NS_THREADMANAGER_CONTRACTID, &rv);
118 NS_ENSURE_SUCCESS(rv, rv);
119 return mgr->GetMainThread(result);
120 #endif
123 #ifndef MOZILLA_INTERNAL_API
124 bool NS_IsMainThread()
126 PRBool result = PR_FALSE;
127 nsCOMPtr<nsIThreadManager> mgr =
128 do_GetService(NS_THREADMANAGER_CONTRACTID);
129 if (mgr)
130 mgr->GetIsMainThread(&result);
131 return bool(result);
133 #elif defined(XP_WIN)
134 extern DWORD gTLSThreadIDIndex;
135 bool
136 NS_IsMainThread()
138 return TlsGetValue(gTLSThreadIDIndex) == (void*) mozilla::threads::Main;
140 #elif !defined(NS_TLS)
141 bool NS_IsMainThread()
143 PRBool result = PR_FALSE;
144 nsThreadManager::get()->nsThreadManager::GetIsMainThread(&result);
145 return bool(result);
147 #elif !defined(MOZ_ENABLE_LIBXUL)
148 bool NS_IsMainThread()
150 return gTLSThreadID == mozilla::threads::Main;
152 #endif
154 NS_METHOD
155 NS_DispatchToCurrentThread(nsIRunnable *event)
157 #ifdef MOZILLA_INTERNAL_API
158 nsIThread *thread = NS_GetCurrentThread();
159 if (!thread) { return NS_ERROR_UNEXPECTED; }
160 #else
161 nsCOMPtr<nsIThread> thread;
162 nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread));
163 NS_ENSURE_SUCCESS(rv, rv);
164 #endif
165 return thread->Dispatch(event, NS_DISPATCH_NORMAL);
168 NS_METHOD
169 NS_DispatchToMainThread(nsIRunnable *event, PRUint32 dispatchFlags)
171 nsCOMPtr<nsIThread> thread;
172 nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
173 NS_ENSURE_SUCCESS(rv, rv);
174 return thread->Dispatch(event, dispatchFlags);
177 #ifndef XPCOM_GLUE_AVOID_NSPR
178 NS_METHOD
179 NS_ProcessPendingEvents(nsIThread *thread, PRIntervalTime timeout)
181 nsresult rv = NS_OK;
183 #ifdef MOZILLA_INTERNAL_API
184 if (!thread) {
185 thread = NS_GetCurrentThread();
186 NS_ENSURE_STATE(thread);
188 #else
189 nsCOMPtr<nsIThread> current;
190 if (!thread) {
191 rv = NS_GetCurrentThread(getter_AddRefs(current));
192 NS_ENSURE_SUCCESS(rv, rv);
193 thread = current.get();
195 #endif
197 PRIntervalTime start = PR_IntervalNow();
198 for (;;) {
199 PRBool processedEvent;
200 rv = thread->ProcessNextEvent(PR_FALSE, &processedEvent);
201 if (NS_FAILED(rv) || !processedEvent)
202 break;
203 if (PR_IntervalNow() - start > timeout)
204 break;
206 return rv;
208 #endif // XPCOM_GLUE_AVOID_NSPR
210 inline PRBool
211 hasPendingEvents(nsIThread *thread)
213 PRBool val;
214 return NS_SUCCEEDED(thread->HasPendingEvents(&val)) && val;
217 PRBool
218 NS_HasPendingEvents(nsIThread *thread)
220 if (!thread) {
221 #ifndef MOZILLA_INTERNAL_API
222 nsCOMPtr<nsIThread> current;
223 NS_GetCurrentThread(getter_AddRefs(current));
224 return hasPendingEvents(current);
225 #else
226 thread = NS_GetCurrentThread();
227 NS_ENSURE_TRUE(thread, PR_FALSE);
228 #endif
230 return hasPendingEvents(thread);
233 PRBool
234 NS_ProcessNextEvent(nsIThread *thread, PRBool mayWait)
236 #ifdef MOZILLA_INTERNAL_API
237 if (!thread) {
238 thread = NS_GetCurrentThread();
239 NS_ENSURE_TRUE(thread, PR_FALSE);
241 #else
242 nsCOMPtr<nsIThread> current;
243 if (!thread) {
244 NS_GetCurrentThread(getter_AddRefs(current));
245 NS_ENSURE_TRUE(current, PR_FALSE);
246 thread = current.get();
248 #endif
249 PRBool val;
250 return NS_SUCCEEDED(thread->ProcessNextEvent(mayWait, &val)) && val;
253 #ifdef MOZILLA_INTERNAL_API
254 nsIThread *
255 NS_GetCurrentThread() {
256 return nsThreadManager::get()->GetCurrentThread();
258 #endif