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
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 code.
17 : *
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.
21 : *
22 : * Contributor(s):
23 : * Darin Fisher <darin@meer.net>
24 : *
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.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #include "nsThreadUtils.h"
40 :
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
48 :
49 : #ifdef XP_WIN
50 : #include <windows.h>
51 : #endif
52 :
53 : #ifndef XPCOM_GLUE_AVOID_NSPR
54 :
55 1447895 : NS_IMPL_THREADSAFE_ISUPPORTS1(nsRunnable, nsIRunnable)
56 :
57 : NS_IMETHODIMP
58 311 : nsRunnable::Run()
59 : {
60 : // Do nothing
61 311 : return NS_OK;
62 : }
63 :
64 : #endif // XPCOM_GLUE_AVOID_NSPR
65 :
66 : //-----------------------------------------------------------------------------
67 :
68 : NS_METHOD
69 5915 : NS_NewThread(nsIThread **result, nsIRunnable *event, PRUint32 stackSize)
70 : {
71 11830 : nsCOMPtr<nsIThread> thread;
72 : #ifdef MOZILLA_INTERNAL_API
73 : nsresult rv = nsThreadManager::get()->
74 5915 : nsThreadManager::NewThread(0, stackSize, 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);
80 :
81 : rv = mgr->NewThread(0, stackSize, getter_AddRefs(thread));
82 : #endif
83 5915 : NS_ENSURE_SUCCESS(rv, rv);
84 :
85 5915 : if (event) {
86 3923 : rv = thread->Dispatch(event, NS_DISPATCH_NORMAL);
87 3923 : NS_ENSURE_SUCCESS(rv, rv);
88 : }
89 :
90 5915 : *result = nsnull;
91 5915 : thread.swap(*result);
92 5915 : return NS_OK;
93 : }
94 :
95 : NS_METHOD
96 55427 : NS_GetCurrentThread(nsIThread **result)
97 : {
98 : #ifdef MOZILLA_INTERNAL_API
99 55427 : 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
107 : }
108 :
109 : NS_METHOD
110 33905 : NS_GetMainThread(nsIThread **result)
111 : {
112 : #ifdef MOZILLA_INTERNAL_API
113 33905 : 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
121 : }
122 :
123 : #ifndef MOZILLA_INTERNAL_API
124 : bool NS_IsMainThread()
125 : {
126 : bool result = false;
127 : nsCOMPtr<nsIThreadManager> mgr =
128 : do_GetService(NS_THREADMANAGER_CONTRACTID);
129 : if (mgr)
130 : mgr->GetIsMainThread(&result);
131 : return bool(result);
132 : }
133 : #elif defined(XP_WIN)
134 : extern DWORD gTLSThreadIDIndex;
135 : bool
136 : NS_IsMainThread()
137 : {
138 : return TlsGetValue(gTLSThreadIDIndex) == (void*) mozilla::threads::Main;
139 : }
140 : #elif !defined(NS_TLS)
141 : bool NS_IsMainThread()
142 : {
143 : bool result = false;
144 : nsThreadManager::get()->nsThreadManager::GetIsMainThread(&result);
145 : return bool(result);
146 : }
147 : #endif
148 :
149 : NS_METHOD
150 1595 : NS_DispatchToCurrentThread(nsIRunnable *event)
151 : {
152 : #ifdef MOZILLA_INTERNAL_API
153 1595 : nsIThread *thread = NS_GetCurrentThread();
154 1595 : if (!thread) { return NS_ERROR_UNEXPECTED; }
155 : #else
156 : nsCOMPtr<nsIThread> thread;
157 : nsresult rv = NS_GetCurrentThread(getter_AddRefs(thread));
158 : NS_ENSURE_SUCCESS(rv, rv);
159 : #endif
160 1541 : return thread->Dispatch(event, NS_DISPATCH_NORMAL);
161 : }
162 :
163 : NS_METHOD
164 29963 : NS_DispatchToMainThread(nsIRunnable *event, PRUint32 dispatchFlags)
165 : {
166 59926 : nsCOMPtr<nsIThread> thread;
167 29963 : nsresult rv = NS_GetMainThread(getter_AddRefs(thread));
168 29963 : NS_ENSURE_SUCCESS(rv, rv);
169 29946 : return thread->Dispatch(event, dispatchFlags);
170 : }
171 :
172 : #ifndef XPCOM_GLUE_AVOID_NSPR
173 : NS_METHOD
174 12892 : NS_ProcessPendingEvents(nsIThread *thread, PRIntervalTime timeout)
175 : {
176 12892 : nsresult rv = NS_OK;
177 :
178 : #ifdef MOZILLA_INTERNAL_API
179 12892 : if (!thread) {
180 79 : thread = NS_GetCurrentThread();
181 79 : NS_ENSURE_STATE(thread);
182 : }
183 : #else
184 : nsCOMPtr<nsIThread> current;
185 : if (!thread) {
186 : rv = NS_GetCurrentThread(getter_AddRefs(current));
187 : NS_ENSURE_SUCCESS(rv, rv);
188 : thread = current.get();
189 : }
190 : #endif
191 :
192 12863 : PRIntervalTime start = PR_IntervalNow();
193 1517 : for (;;) {
194 : bool processedEvent;
195 14380 : rv = thread->ProcessNextEvent(false, &processedEvent);
196 14380 : if (NS_FAILED(rv) || !processedEvent)
197 12863 : break;
198 1517 : if (PR_IntervalNow() - start > timeout)
199 0 : break;
200 : }
201 12863 : return rv;
202 : }
203 : #endif // XPCOM_GLUE_AVOID_NSPR
204 :
205 : inline bool
206 332672 : hasPendingEvents(nsIThread *thread)
207 : {
208 : bool val;
209 332672 : return NS_SUCCEEDED(thread->HasPendingEvents(&val)) && val;
210 : }
211 :
212 : bool
213 332672 : NS_HasPendingEvents(nsIThread *thread)
214 : {
215 332672 : if (!thread) {
216 : #ifndef MOZILLA_INTERNAL_API
217 : nsCOMPtr<nsIThread> current;
218 : NS_GetCurrentThread(getter_AddRefs(current));
219 : return hasPendingEvents(current);
220 : #else
221 0 : thread = NS_GetCurrentThread();
222 0 : NS_ENSURE_TRUE(thread, false);
223 : #endif
224 : }
225 332672 : return hasPendingEvents(thread);
226 : }
227 :
228 : bool
229 140570 : NS_ProcessNextEvent(nsIThread *thread, bool mayWait)
230 : {
231 : #ifdef MOZILLA_INTERNAL_API
232 140570 : if (!thread) {
233 1175 : thread = NS_GetCurrentThread();
234 1175 : NS_ENSURE_TRUE(thread, false);
235 : }
236 : #else
237 : nsCOMPtr<nsIThread> current;
238 : if (!thread) {
239 : NS_GetCurrentThread(getter_AddRefs(current));
240 : NS_ENSURE_TRUE(current, false);
241 : thread = current.get();
242 : }
243 : #endif
244 : bool val;
245 140570 : return NS_SUCCEEDED(thread->ProcessNextEvent(mayWait, &val)) && val;
246 : }
247 :
248 : #ifdef MOZILLA_INTERNAL_API
249 : nsIThread *
250 27640 : NS_GetCurrentThread() {
251 27640 : return nsThreadManager::get()->GetCurrentThread();
252 : }
253 : #endif
|