/src/mozilla-central/xpcom/threads/nsThreadUtils.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef nsThreadUtils_h__ |
8 | | #define nsThreadUtils_h__ |
9 | | |
10 | | #include "prthread.h" |
11 | | #include "prinrval.h" |
12 | | #include "MainThreadUtils.h" |
13 | | #include "nsICancelableRunnable.h" |
14 | | #include "nsIIdlePeriod.h" |
15 | | #include "nsIIdleRunnable.h" |
16 | | #include "nsINamed.h" |
17 | | #include "nsIRunnable.h" |
18 | | #include "nsIThreadManager.h" |
19 | | #include "nsITimer.h" |
20 | | #include "nsIThread.h" |
21 | | #include "nsString.h" |
22 | | #include "nsCOMPtr.h" |
23 | | #include "nsAutoPtr.h" |
24 | | #include "xpcpublic.h" |
25 | | #include "mozilla/Atomics.h" |
26 | | #include "mozilla/Likely.h" |
27 | | #include "mozilla/Maybe.h" |
28 | | #include "mozilla/Move.h" |
29 | | #include "mozilla/TimeStamp.h" |
30 | | #include "mozilla/Tuple.h" |
31 | | #include "mozilla/TypeTraits.h" |
32 | | |
33 | | #include <utility> |
34 | | |
35 | | //----------------------------------------------------------------------------- |
36 | | // These methods are alternatives to the methods on nsIThreadManager, provided |
37 | | // for convenience. |
38 | | |
39 | | /** |
40 | | * Create a new thread, and optionally provide an initial event for the thread. |
41 | | * |
42 | | * @param aResult |
43 | | * The resulting nsIThread object. |
44 | | * @param aInitialEvent |
45 | | * The initial event to run on this thread. This parameter may be null. |
46 | | * @param aStackSize |
47 | | * The size in bytes to reserve for the thread's stack. |
48 | | * |
49 | | * @returns NS_ERROR_INVALID_ARG |
50 | | * Indicates that the given name is not unique. |
51 | | */ |
52 | | extern nsresult |
53 | | NS_NewThread(nsIThread** aResult, |
54 | | nsIRunnable* aInitialEvent = nullptr, |
55 | | uint32_t aStackSize = nsIThreadManager::DEFAULT_STACK_SIZE); |
56 | | |
57 | | /** |
58 | | * Creates a named thread, otherwise the same as NS_NewThread |
59 | | */ |
60 | | extern nsresult |
61 | | NS_NewNamedThread(const nsACString& aName, |
62 | | nsIThread** aResult, |
63 | | nsIRunnable* aInitialEvent = nullptr, |
64 | | uint32_t aStackSize = nsIThreadManager::DEFAULT_STACK_SIZE); |
65 | | |
66 | | template<size_t LEN> |
67 | | inline nsresult |
68 | | NS_NewNamedThread(const char (&aName)[LEN], |
69 | | nsIThread** aResult, |
70 | | nsIRunnable* aInitialEvent = nullptr, |
71 | | uint32_t aStackSize = nsIThreadManager::DEFAULT_STACK_SIZE) |
72 | 0 | { |
73 | 0 | static_assert(LEN <= 16, |
74 | 0 | "Thread name must be no more than 16 characters"); |
75 | 0 | return NS_NewNamedThread(nsDependentCString(aName, LEN - 1), |
76 | 0 | aResult, aInitialEvent, aStackSize); |
77 | 0 | } |
78 | | |
79 | | /** |
80 | | * Get a reference to the current thread, creating it if it does not exist yet. |
81 | | * |
82 | | * @param aResult |
83 | | * The resulting nsIThread object. |
84 | | */ |
85 | | extern nsresult NS_GetCurrentThread(nsIThread** aResult); |
86 | | |
87 | | /** |
88 | | * Dispatch the given event to the current thread. |
89 | | * |
90 | | * @param aEvent |
91 | | * The event to dispatch. |
92 | | * |
93 | | * @returns NS_ERROR_INVALID_ARG |
94 | | * If event is null. |
95 | | */ |
96 | | extern nsresult NS_DispatchToCurrentThread(nsIRunnable* aEvent); |
97 | | extern nsresult |
98 | | NS_DispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent); |
99 | | |
100 | | /** |
101 | | * Dispatch the given event to the main thread. |
102 | | * |
103 | | * @param aEvent |
104 | | * The event to dispatch. |
105 | | * @param aDispatchFlags |
106 | | * The flags to pass to the main thread's dispatch method. |
107 | | * |
108 | | * @returns NS_ERROR_INVALID_ARG |
109 | | * If event is null. |
110 | | */ |
111 | | extern nsresult |
112 | | NS_DispatchToMainThread(nsIRunnable* aEvent, |
113 | | uint32_t aDispatchFlags = NS_DISPATCH_NORMAL); |
114 | | extern nsresult |
115 | | NS_DispatchToMainThread(already_AddRefed<nsIRunnable>&& aEvent, |
116 | | uint32_t aDispatchFlags = NS_DISPATCH_NORMAL); |
117 | | |
118 | | extern nsresult |
119 | | NS_DelayedDispatchToCurrentThread( |
120 | | already_AddRefed<nsIRunnable>&& aEvent, uint32_t aDelayMs); |
121 | | |
122 | | /** |
123 | | * Dispatch the given event to the idle queue of the current thread. |
124 | | * |
125 | | * @param aEvent |
126 | | * The event to dispatch. |
127 | | * |
128 | | * @returns NS_ERROR_INVALID_ARG |
129 | | * If event is null. |
130 | | * @returns NS_ERROR_UNEXPECTED |
131 | | * If the thread is shutting down. |
132 | | */ |
133 | | extern nsresult |
134 | | NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent); |
135 | | |
136 | | /** |
137 | | * Dispatch the given event to the idle queue of the current thread. |
138 | | * |
139 | | * @param aEvent The event to dispatch. If the event implements |
140 | | * nsIIdleRunnable, it will receive a call on |
141 | | * nsIIdleRunnable::SetTimer when dispatched, with the value of |
142 | | * aTimeout. |
143 | | * |
144 | | * @param aTimeout The time in milliseconds until the event should be |
145 | | * moved from the idle queue to the regular queue, if it hasn't been |
146 | | * executed. If aEvent is also an nsIIdleRunnable, it is expected |
147 | | * that it should handle the timeout itself, after a call to |
148 | | * nsIIdleRunnable::SetTimer. |
149 | | * |
150 | | * @returns NS_ERROR_INVALID_ARG |
151 | | * If event is null. |
152 | | * @returns NS_ERROR_UNEXPECTED |
153 | | * If the thread is shutting down. |
154 | | */ |
155 | | extern nsresult |
156 | | NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aTimeout); |
157 | | |
158 | | /** |
159 | | * Dispatch the given event to the idle queue of a thread. |
160 | | * |
161 | | * @param aEvent The event to dispatch. |
162 | | * |
163 | | * @param aThread The target thread for the dispatch. |
164 | | * |
165 | | * @returns NS_ERROR_INVALID_ARG |
166 | | * If event is null. |
167 | | * @returns NS_ERROR_UNEXPECTED |
168 | | * If the thread is shutting down. |
169 | | */ |
170 | | extern nsresult |
171 | | NS_IdleDispatchToThread(already_AddRefed<nsIRunnable>&& aEvent, |
172 | | nsIThread* aThread); |
173 | | |
174 | | /** |
175 | | * Dispatch the given event to the idle queue of a thread. |
176 | | * |
177 | | * @param aEvent The event to dispatch. If the event implements |
178 | | * nsIIdleRunnable, it will receive a call on |
179 | | * nsIIdleRunnable::SetTimer when dispatched, with the value of |
180 | | * aTimeout. |
181 | | * |
182 | | * @param aTimeout The time in milliseconds until the event should be |
183 | | * moved from the idle queue to the regular queue, if it hasn't been |
184 | | * executed. If aEvent is also an nsIIdleRunnable, it is expected |
185 | | * that it should handle the timeout itself, after a call to |
186 | | * nsIIdleRunnable::SetTimer. |
187 | | * |
188 | | * @param aThread The target thread for the dispatch. |
189 | | * |
190 | | * @returns NS_ERROR_INVALID_ARG |
191 | | * If event is null. |
192 | | * @returns NS_ERROR_UNEXPECTED |
193 | | * If the thread is shutting down. |
194 | | */ |
195 | | extern nsresult |
196 | | NS_IdleDispatchToThread(already_AddRefed<nsIRunnable>&& aEvent, |
197 | | uint32_t aTimeout, |
198 | | nsIThread* aThread); |
199 | | |
200 | | #ifndef XPCOM_GLUE_AVOID_NSPR |
201 | | /** |
202 | | * Process all pending events for the given thread before returning. This |
203 | | * method simply calls ProcessNextEvent on the thread while HasPendingEvents |
204 | | * continues to return true and the time spent in NS_ProcessPendingEvents |
205 | | * does not exceed the given timeout value. |
206 | | * |
207 | | * @param aThread |
208 | | * The thread object for which to process pending events. If null, then |
209 | | * events will be processed for the current thread. |
210 | | * @param aTimeout |
211 | | * The maximum number of milliseconds to spend processing pending events. |
212 | | * Events are not pre-empted to honor this timeout. Rather, the timeout |
213 | | * value is simply used to determine whether or not to process another event. |
214 | | * Pass PR_INTERVAL_NO_TIMEOUT to specify no timeout. |
215 | | */ |
216 | | extern nsresult |
217 | | NS_ProcessPendingEvents(nsIThread* aThread, |
218 | | PRIntervalTime aTimeout = PR_INTERVAL_NO_TIMEOUT); |
219 | | #endif |
220 | | |
221 | | /** |
222 | | * Shortcut for nsIThread::HasPendingEvents. |
223 | | * |
224 | | * It is an error to call this function when the given thread is not the |
225 | | * current thread. This function will return false if called from some |
226 | | * other thread. |
227 | | * |
228 | | * @param aThread |
229 | | * The current thread or null. |
230 | | * |
231 | | * @returns |
232 | | * A boolean value that if "true" indicates that there are pending events |
233 | | * in the current thread's event queue. |
234 | | */ |
235 | | extern bool NS_HasPendingEvents(nsIThread* aThread = nullptr); |
236 | | |
237 | | /** |
238 | | * Shortcut for nsIThread::ProcessNextEvent. |
239 | | * |
240 | | * It is an error to call this function when the given thread is not the |
241 | | * current thread. This function will simply return false if called |
242 | | * from some other thread. |
243 | | * |
244 | | * @param aThread |
245 | | * The current thread or null. |
246 | | * @param aMayWait |
247 | | * A boolean parameter that if "true" indicates that the method may block |
248 | | * the calling thread to wait for a pending event. |
249 | | * |
250 | | * @returns |
251 | | * A boolean value that if "true" indicates that an event from the current |
252 | | * thread's event queue was processed. |
253 | | */ |
254 | | extern bool NS_ProcessNextEvent(nsIThread* aThread = nullptr, |
255 | | bool aMayWait = true); |
256 | | |
257 | | // A wrapper for nested event loops. |
258 | | // |
259 | | // This function is intended to make code more obvious (do you remember |
260 | | // what NS_ProcessNextEvent(nullptr, true) means?) and slightly more |
261 | | // efficient, as people often pass nullptr or NS_GetCurrentThread to |
262 | | // NS_ProcessNextEvent, which results in needless querying of the current |
263 | | // thread every time through the loop. |
264 | | // |
265 | | // You should use this function in preference to NS_ProcessNextEvent inside |
266 | | // a loop unless one of the following is true: |
267 | | // |
268 | | // * You need to pass `false` to NS_ProcessNextEvent; or |
269 | | // * You need to do unusual things around the call to NS_ProcessNextEvent, |
270 | | // such as unlocking mutexes that you are holding. |
271 | | // |
272 | | // If you *do* need to call NS_ProcessNextEvent manually, please do call |
273 | | // NS_GetCurrentThread() outside of your loop and pass the returned pointer |
274 | | // into NS_ProcessNextEvent for a tiny efficiency win. |
275 | | namespace mozilla { |
276 | | |
277 | | // You should normally not need to deal with this template parameter. If |
278 | | // you enjoy esoteric event loop details, read on. |
279 | | // |
280 | | // If you specify that NS_ProcessNextEvent wait for an event, it is possible |
281 | | // for NS_ProcessNextEvent to return false, i.e. to indicate that an event |
282 | | // was not processed. This can only happen when the thread has been shut |
283 | | // down by another thread, but is still attempting to process events outside |
284 | | // of a nested event loop. |
285 | | // |
286 | | // This behavior is admittedly strange. The scenario it deals with is the |
287 | | // following: |
288 | | // |
289 | | // * The current thread has been shut down by some owner thread. |
290 | | // * The current thread is spinning an event loop waiting for some condition |
291 | | // to become true. |
292 | | // * Said condition is actually being fulfilled by another thread, so there |
293 | | // are timing issues in play. |
294 | | // |
295 | | // Thus, there is a small window where the current thread's event loop |
296 | | // spinning can check the condition, find it false, and call |
297 | | // NS_ProcessNextEvent to wait for another event. But we don't actually |
298 | | // want it to wait indefinitely, because there might not be any other events |
299 | | // in the event loop, and the current thread can't accept dispatched events |
300 | | // because it's being shut down. Thus, actually blocking would hang the |
301 | | // thread, which is bad. The solution, then, is to detect such a scenario |
302 | | // and not actually block inside NS_ProcessNextEvent. |
303 | | // |
304 | | // But this is a problem, because we want to return the status of |
305 | | // NS_ProcessNextEvent to the caller of SpinEventLoopUntil if possible. In |
306 | | // the above scenario, however, we'd stop spinning prematurely and cause |
307 | | // all sorts of havoc. We therefore have this template parameter to |
308 | | // control whether errors are ignored or passed out to the caller of |
309 | | // SpinEventLoopUntil. The latter is the default; if you find yourself |
310 | | // wanting to use the former, you should think long and hard before doing |
311 | | // so, and write a comment like this defending your choice. |
312 | | |
313 | | enum class ProcessFailureBehavior { |
314 | | IgnoreAndContinue, |
315 | | ReportToCaller, |
316 | | }; |
317 | | |
318 | | template<ProcessFailureBehavior Behavior = ProcessFailureBehavior::ReportToCaller, |
319 | | typename Pred> |
320 | | bool |
321 | | SpinEventLoopUntil(Pred&& aPredicate, nsIThread* aThread = nullptr) |
322 | 0 | { |
323 | 0 | nsIThread* thread = aThread ? aThread : NS_GetCurrentThread(); |
324 | 0 |
|
325 | 0 | // From a latency perspective, spinning the event loop is like leaving script |
326 | 0 | // and returning to the event loop. Tell the watchdog we stopped running |
327 | 0 | // script (until we return). |
328 | 0 | mozilla::Maybe<xpc::AutoScriptActivity> asa; |
329 | 0 | if (NS_IsMainThread()) { |
330 | 0 | asa.emplace(false); |
331 | 0 | } |
332 | 0 |
|
333 | 0 | while (!aPredicate()) { |
334 | 0 | bool didSomething = NS_ProcessNextEvent(thread, true); |
335 | 0 |
|
336 | 0 | if (Behavior == ProcessFailureBehavior::IgnoreAndContinue) { |
337 | 0 | // Don't care what happened, continue on. |
338 | 0 | continue; |
339 | 0 | } else if (!didSomething) { |
340 | 0 | return false; |
341 | 0 | } |
342 | 0 | } |
343 | 0 |
|
344 | 0 | return true; |
345 | 0 | } Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, TestBufferedInputStream_AsyncWait_async_Test::TestBody()::$_0>(TestBufferedInputStream_AsyncWait_async_Test::TestBody()::$_0&&, nsIThread*) Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, TestBufferedInputStream_AsyncWait_async_closureOnly_Test::TestBody()::$_1>(TestBufferedInputStream_AsyncWait_async_closureOnly_Test::TestBody()::$_1&&, nsIThread*) Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, TestNsMIMEInputStream_AsyncInputStreamLength_Test::TestBody()::$_2>(TestNsMIMEInputStream_AsyncInputStreamLength_Test::TestBody()::$_2&&, nsIThread*) Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, TestNsMIMEInputStream_NegativeAsyncInputStreamLength_Test::TestBody()::$_3>(TestNsMIMEInputStream_NegativeAsyncInputStreamLength_Test::TestBody()::$_3&&, nsIThread*) Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, TestNsMIMEInputStream_AbortLengthCallback_Test::TestBody()::$_4>(TestNsMIMEInputStream_AbortLengthCallback_Test::TestBody()::$_4&&, nsIThread*) Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, TestPartiallySeekableInputStream_AsyncInputStreamLength_Test::TestBody()::$_5>(TestPartiallySeekableInputStream_AsyncInputStreamLength_Test::TestBody()::$_5&&, nsIThread*) Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, TestPartiallySeekableInputStream_NegativeAsyncInputStreamLength_Test::TestBody()::$_6>(TestPartiallySeekableInputStream_NegativeAsyncInputStreamLength_Test::TestBody()::$_6&&, nsIThread*) Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:bool mozilla::SpinEventLoopUntil<(mozilla::ProcessFailureBehavior)1, TestPartiallySeekableInputStream_AbortLengthCallback_Test::TestBody()::$_7>(TestPartiallySeekableInputStream_AbortLengthCallback_Test::TestBody()::$_7&&, nsIThread*) |
346 | | |
347 | | } // namespace mozilla |
348 | | |
349 | | /** |
350 | | * Returns true if we're in the compositor thread. |
351 | | * |
352 | | * We declare this here because the headers required to invoke |
353 | | * CompositorThreadHolder::IsInCompositorThread() also pull in a bunch of system |
354 | | * headers that #define various tokens in a way that can break the build. |
355 | | */ |
356 | | extern bool NS_IsInCompositorThread(); |
357 | | |
358 | | extern bool NS_IsInVRThread(); |
359 | | |
360 | | //----------------------------------------------------------------------------- |
361 | | // Helpers that work with nsCOMPtr: |
362 | | |
363 | | inline already_AddRefed<nsIThread> |
364 | | do_GetCurrentThread() |
365 | | { |
366 | | nsIThread* thread = nullptr; |
367 | | NS_GetCurrentThread(&thread); |
368 | | return already_AddRefed<nsIThread>(thread); |
369 | | } |
370 | | |
371 | | inline already_AddRefed<nsIThread> |
372 | | do_GetMainThread() |
373 | | { |
374 | | nsIThread* thread = nullptr; |
375 | | NS_GetMainThread(&thread); |
376 | | return already_AddRefed<nsIThread>(thread); |
377 | | } |
378 | | |
379 | | //----------------------------------------------------------------------------- |
380 | | |
381 | | #ifdef MOZILLA_INTERNAL_API |
382 | | // Fast access to the current thread. Will create an nsIThread if one does not |
383 | | // exist already! Do not release the returned pointer! If you want to use this |
384 | | // pointer from some other thread, then you will need to AddRef it. Otherwise, |
385 | | // you should only consider this pointer valid from code running on the current |
386 | | // thread. |
387 | | extern nsIThread* NS_GetCurrentThread(); |
388 | | |
389 | | // Exactly the same as NS_GetCurrentThread, except it will not create an |
390 | | // nsThread if one does not exist yet. This is useful in cases where you have |
391 | | // code that runs on threads that may or may not not be driven by an nsThread |
392 | | // event loop, and wish to avoid inadvertently creating a superfluous nsThread. |
393 | | extern nsIThread* NS_GetCurrentThreadNoCreate(); |
394 | | |
395 | | /** |
396 | | * Set the name of the current thread. Prefer this function over |
397 | | * PR_SetCurrentThreadName() if possible. The name will also be included in the |
398 | | * crash report. |
399 | | * |
400 | | * @param aName |
401 | | * Name of the thread. A C language null-terminated string. |
402 | | */ |
403 | | extern void NS_SetCurrentThreadName(const char* aName); |
404 | | #endif |
405 | | |
406 | | //----------------------------------------------------------------------------- |
407 | | |
408 | | #ifndef XPCOM_GLUE_AVOID_NSPR |
409 | | |
410 | | namespace mozilla { |
411 | | |
412 | | // This class is designed to be subclassed. |
413 | | class IdlePeriod : public nsIIdlePeriod |
414 | | { |
415 | | public: |
416 | | NS_DECL_THREADSAFE_ISUPPORTS |
417 | | NS_DECL_NSIIDLEPERIOD |
418 | | |
419 | | IdlePeriod() {} |
420 | | |
421 | | protected: |
422 | | virtual ~IdlePeriod() {} |
423 | | private: |
424 | | IdlePeriod(const IdlePeriod&) = delete; |
425 | | IdlePeriod& operator=(const IdlePeriod&) = delete; |
426 | | IdlePeriod& operator=(const IdlePeriod&&) = delete; |
427 | | }; |
428 | | |
429 | | // Cancelable runnable methods implement nsICancelableRunnable, and |
430 | | // Idle and IdleWithTimer also nsIIdleRunnable. |
431 | | enum class RunnableKind |
432 | | { |
433 | | Standard, |
434 | | Cancelable, |
435 | | Idle, |
436 | | IdleWithTimer |
437 | | }; |
438 | | |
439 | | // Implementing nsINamed on Runnable bloats vtables for the hundreds of |
440 | | // Runnable subclasses that we have, so we want to avoid that overhead |
441 | | // when we're not using nsINamed for anything. |
442 | | #ifndef RELEASE_OR_BETA |
443 | | #define MOZ_COLLECTING_RUNNABLE_TELEMETRY |
444 | | #endif |
445 | | |
446 | | // This class is designed to be subclassed. |
447 | | class Runnable |
448 | | : public nsIRunnable |
449 | | #ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY |
450 | | , public nsINamed |
451 | | #endif |
452 | | { |
453 | | public: |
454 | | // Runnable refcount changes are preserved when recording/replaying to ensure |
455 | | // that they are destroyed at consistent points. |
456 | | NS_DECL_THREADSAFE_ISUPPORTS_WITH_RECORDING(recordreplay::Behavior::Preserve) |
457 | | NS_DECL_NSIRUNNABLE |
458 | | #ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY |
459 | | NS_DECL_NSINAMED |
460 | | #endif |
461 | | |
462 | | Runnable() = delete; |
463 | | |
464 | | #ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY |
465 | | explicit Runnable(const char* aName) : mName(aName) {} |
466 | | #else |
467 | | explicit Runnable(const char* aName) {} |
468 | | #endif |
469 | | |
470 | | protected: |
471 | | virtual ~Runnable() {} |
472 | | |
473 | | #ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY |
474 | | const char* mName = nullptr; |
475 | | #endif |
476 | | |
477 | | private: |
478 | | Runnable(const Runnable&) = delete; |
479 | | Runnable& operator=(const Runnable&) = delete; |
480 | | Runnable& operator=(const Runnable&&) = delete; |
481 | | }; |
482 | | |
483 | | // This class is designed to be subclassed. |
484 | | class CancelableRunnable : public Runnable, |
485 | | public nsICancelableRunnable |
486 | | { |
487 | | public: |
488 | | NS_DECL_ISUPPORTS_INHERITED |
489 | | // nsICancelableRunnable |
490 | | virtual nsresult Cancel() override; |
491 | | |
492 | | CancelableRunnable() = delete; |
493 | | explicit CancelableRunnable(const char* aName) : Runnable(aName) {} |
494 | | |
495 | | protected: |
496 | | virtual ~CancelableRunnable() {} |
497 | | private: |
498 | | CancelableRunnable(const CancelableRunnable&) = delete; |
499 | | CancelableRunnable& operator=(const CancelableRunnable&) = delete; |
500 | | CancelableRunnable& operator=(const CancelableRunnable&&) = delete; |
501 | | }; |
502 | | |
503 | | // This class is designed to be subclassed. |
504 | | class IdleRunnable : public CancelableRunnable, |
505 | | public nsIIdleRunnable |
506 | | { |
507 | | public: |
508 | | NS_DECL_ISUPPORTS_INHERITED |
509 | | |
510 | | IdleRunnable() |
511 | | : CancelableRunnable("IdleRunnable") |
512 | | { |
513 | | } |
514 | 83 | explicit IdleRunnable(const char* aName) : CancelableRunnable(aName) {} |
515 | | |
516 | | protected: |
517 | | virtual ~IdleRunnable() {} |
518 | | private: |
519 | | IdleRunnable(const IdleRunnable&) = delete; |
520 | | IdleRunnable& operator=(const IdleRunnable&) = delete; |
521 | | IdleRunnable& operator=(const IdleRunnable&&) = delete; |
522 | | }; |
523 | | |
524 | | // This class is designed to be a wrapper of a real runnable to support event |
525 | | // prioritizable. |
526 | | class PrioritizableRunnable : public Runnable, public nsIRunnablePriority |
527 | | { |
528 | | public: |
529 | | PrioritizableRunnable(already_AddRefed<nsIRunnable>&& aRunnable, |
530 | | uint32_t aPriority); |
531 | | |
532 | | #ifdef MOZ_COLLECTING_RUNNABLE_TELEMETRY |
533 | | NS_IMETHOD GetName(nsACString& aName) override; |
534 | | #endif |
535 | | |
536 | | NS_DECL_ISUPPORTS_INHERITED |
537 | | NS_DECL_NSIRUNNABLE |
538 | | NS_DECL_NSIRUNNABLEPRIORITY |
539 | | |
540 | | protected: |
541 | | virtual ~PrioritizableRunnable() {}; |
542 | | nsCOMPtr<nsIRunnable> mRunnable; |
543 | | uint32_t mPriority; |
544 | | }; |
545 | | |
546 | | namespace detail { |
547 | | |
548 | | // An event that can be used to call a C++11 functions or function objects, |
549 | | // including lambdas. The function must have no required arguments, and must |
550 | | // return void. |
551 | | template<typename StoredFunction> |
552 | | class RunnableFunction : public Runnable |
553 | | { |
554 | | public: |
555 | | template <typename F> |
556 | | explicit RunnableFunction(const char* aName, F&& aFunction) |
557 | | : Runnable(aName) |
558 | | , mFunction(std::forward<F>(aFunction)) |
559 | 0 | { } Unexecuted instantiation: Unified_cpp_image0.cpp:mozilla::detail::RunnableFunction<mozilla::image::IDecodingTask::NotifyProgress(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_1>::RunnableFunction<mozilla::image::IDecodingTask::NotifyProgress(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_1>(char const*, mozilla::image::IDecodingTask::NotifyProgress(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_1&&) Unexecuted instantiation: Unified_cpp_image0.cpp:mozilla::detail::RunnableFunction<mozilla::image::IDecodingTask::NotifyDecodeComplete(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_2>::RunnableFunction<mozilla::image::IDecodingTask::NotifyDecodeComplete(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_2>(char const*, mozilla::image::IDecodingTask::NotifyDecodeComplete(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_2&&) Unexecuted instantiation: Unified_cpp_image0.cpp:mozilla::detail::RunnableFunction<mozilla::image::ImageResource::SendOnUnlockedDraw(unsigned int)::$_3>::RunnableFunction<mozilla::image::ImageResource::SendOnUnlockedDraw(unsigned int)::$_3>(char const*, mozilla::image::ImageResource::SendOnUnlockedDraw(unsigned int)::$_3&&) Unexecuted instantiation: Unified_cpp_image1.cpp:mozilla::detail::RunnableFunction<mozilla::image::RasterImage::OnSurfaceDiscarded(mozilla::image::SurfaceKey const&)::$_8>::RunnableFunction<mozilla::image::RasterImage::OnSurfaceDiscarded(mozilla::image::SurfaceKey const&)::$_8>(char const*, mozilla::image::RasterImage::OnSurfaceDiscarded(mozilla::image::SurfaceKey const&)::$_8&&) Unexecuted instantiation: Unified_cpp_image1.cpp:mozilla::detail::RunnableFunction<mozilla::image::VectorImage::SendFrameComplete(bool, unsigned int)::$_9>::RunnableFunction<mozilla::image::VectorImage::SendFrameComplete(bool, unsigned int)::$_9>(char const*, mozilla::image::VectorImage::SendFrameComplete(bool, unsigned int)::$_9&&) Unexecuted instantiation: TelemetryCommon.cpp:mozilla::detail::RunnableFunction<mozilla::Telemetry::Common::LogToBrowserConsole(unsigned int, nsTSubstring<char16_t> const&)::$_0>::RunnableFunction<mozilla::Telemetry::Common::LogToBrowserConsole(unsigned int, nsTSubstring<char16_t> const&)::$_0>(char const*, mozilla::Telemetry::Common::LogToBrowserConsole(unsigned int, nsTSubstring<char16_t> const&)::$_0&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<(anonymous namespace)::PersistenceThreadLoadData()::$_5::operator()() const::{lambda()#1}>::RunnableFunction<{lambda()#1}>(char const*, {lambda()#1}&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<(anonymous namespace)::MainThreadArmPersistenceTimer()::$_3::operator()(nsITimer*, void*) const::{lambda()#1}>::RunnableFunction<{lambda()#1}>(char const*, {lambda()#1}&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<(anonymous namespace)::PersistenceThreadPersist()::$_4::operator()() const::{lambda()#1}>::RunnableFunction<{lambda()#1}>(char const*, {lambda()#1}&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<TelemetryGeckoViewTesting::TestDispatchPersist()::$_0>::RunnableFunction<TelemetryGeckoViewTesting::TestDispatchPersist()::$_0>(char const*, TelemetryGeckoViewTesting::TestDispatchPersist()::$_0&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<TelemetryGeckoViewPersistence::ClearPersistenceData()::$_1>::RunnableFunction<TelemetryGeckoViewPersistence::ClearPersistenceData()::$_1>(char const*, TelemetryGeckoViewPersistence::ClearPersistenceData()::$_1&&) |
560 | | |
561 | 0 | NS_IMETHOD Run() override { |
562 | 0 | static_assert(IsVoid<decltype(mFunction())>::value, |
563 | 0 | "The lambda must return void!"); |
564 | 0 | mFunction(); |
565 | 0 | return NS_OK; |
566 | 0 | } Unexecuted instantiation: Unified_cpp_image0.cpp:mozilla::detail::RunnableFunction<mozilla::image::IDecodingTask::NotifyProgress(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_1>::Run() Unexecuted instantiation: Unified_cpp_image0.cpp:mozilla::detail::RunnableFunction<mozilla::image::IDecodingTask::NotifyDecodeComplete(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_2>::Run() Unexecuted instantiation: Unified_cpp_image0.cpp:mozilla::detail::RunnableFunction<mozilla::image::ImageResource::SendOnUnlockedDraw(unsigned int)::$_3>::Run() Unexecuted instantiation: Unified_cpp_image1.cpp:mozilla::detail::RunnableFunction<mozilla::image::RasterImage::OnSurfaceDiscarded(mozilla::image::SurfaceKey const&)::$_8>::Run() Unexecuted instantiation: Unified_cpp_image1.cpp:mozilla::detail::RunnableFunction<mozilla::image::VectorImage::SendFrameComplete(bool, unsigned int)::$_9>::Run() Unexecuted instantiation: TelemetryCommon.cpp:mozilla::detail::RunnableFunction<mozilla::Telemetry::Common::LogToBrowserConsole(unsigned int, nsTSubstring<char16_t> const&)::$_0>::Run() Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<(anonymous namespace)::PersistenceThreadLoadData()::$_5::operator()() const::{lambda()#1}>::Run() Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<(anonymous namespace)::MainThreadArmPersistenceTimer()::$_3::operator()(nsITimer*, void*) const::{lambda()#1}>::Run() Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<(anonymous namespace)::PersistenceThreadPersist()::$_4::operator()() const::{lambda()#1}>::Run() Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<TelemetryGeckoViewTesting::TestDispatchPersist()::$_0>::Run() Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:mozilla::detail::RunnableFunction<TelemetryGeckoViewPersistence::ClearPersistenceData()::$_1>::Run() |
567 | | private: |
568 | | StoredFunction mFunction; |
569 | | }; |
570 | | |
571 | | // Type alias for NS_NewRunnableFunction |
572 | | template<typename Function> |
573 | | using RunnableFunctionImpl = |
574 | | // Make sure we store a non-reference in nsRunnableFunction. |
575 | | typename detail::RunnableFunction<typename RemoveReference<Function>::Type>; |
576 | | } // namespace detail |
577 | | |
578 | | namespace detail { |
579 | | |
580 | | template<typename CVRemoved> |
581 | | struct IsRefcountedSmartPointerHelper : FalseType {}; |
582 | | |
583 | | template<typename Pointee> |
584 | | struct IsRefcountedSmartPointerHelper<RefPtr<Pointee>> : TrueType {}; |
585 | | |
586 | | template<typename Pointee> |
587 | | struct IsRefcountedSmartPointerHelper<nsCOMPtr<Pointee>> : TrueType {}; |
588 | | |
589 | | } // namespace detail |
590 | | |
591 | | template<typename T> |
592 | | struct IsRefcountedSmartPointer |
593 | | : detail::IsRefcountedSmartPointerHelper<typename RemoveCV<T>::Type> |
594 | | {}; |
595 | | |
596 | | namespace detail { |
597 | | |
598 | | template<typename T, typename CVRemoved> |
599 | | struct RemoveSmartPointerHelper |
600 | | { |
601 | | typedef T Type; |
602 | | }; |
603 | | |
604 | | template<typename T, typename Pointee> |
605 | | struct RemoveSmartPointerHelper<T, RefPtr<Pointee>> |
606 | | { |
607 | | typedef Pointee Type; |
608 | | }; |
609 | | |
610 | | template<typename T, typename Pointee> |
611 | | struct RemoveSmartPointerHelper<T, nsCOMPtr<Pointee>> |
612 | | { |
613 | | typedef Pointee Type; |
614 | | }; |
615 | | |
616 | | } // namespace detail |
617 | | |
618 | | template<typename T> |
619 | | struct RemoveSmartPointer |
620 | | : detail::RemoveSmartPointerHelper<T, typename RemoveCV<T>::Type> |
621 | | {}; |
622 | | |
623 | | namespace detail { |
624 | | |
625 | | template<typename T, typename CVRemoved> |
626 | | struct RemoveRawOrSmartPointerHelper |
627 | | { |
628 | | typedef T Type; |
629 | | }; |
630 | | |
631 | | template<typename T, typename Pointee> |
632 | | struct RemoveRawOrSmartPointerHelper<T, Pointee*> |
633 | | { |
634 | | typedef Pointee Type; |
635 | | }; |
636 | | |
637 | | template<typename T, typename Pointee> |
638 | | struct RemoveRawOrSmartPointerHelper<T, RefPtr<Pointee>> |
639 | | { |
640 | | typedef Pointee Type; |
641 | | }; |
642 | | |
643 | | template<typename T, typename Pointee> |
644 | | struct RemoveRawOrSmartPointerHelper<T, nsCOMPtr<Pointee>> |
645 | | { |
646 | | typedef Pointee Type; |
647 | | }; |
648 | | |
649 | | } // namespace detail |
650 | | |
651 | | template<typename T> |
652 | | struct RemoveRawOrSmartPointer |
653 | | : detail::RemoveRawOrSmartPointerHelper<T, typename RemoveCV<T>::Type> |
654 | | {}; |
655 | | |
656 | | } // namespace mozilla |
657 | | |
658 | | inline nsISupports* |
659 | | ToSupports(mozilla::Runnable *p) |
660 | | { |
661 | | return static_cast<nsIRunnable*>(p); |
662 | | } |
663 | | |
664 | | template<typename Function> |
665 | | already_AddRefed<mozilla::Runnable> |
666 | | NS_NewRunnableFunction(const char* aName, Function&& aFunction) |
667 | 0 | { |
668 | 0 | // We store a non-reference in RunnableFunction, but still forward aFunction |
669 | 0 | // to move if possible. |
670 | 0 | return do_AddRef( |
671 | 0 | new mozilla::detail::RunnableFunctionImpl<Function>( |
672 | 0 | aName, std::forward<Function>(aFunction))); |
673 | 0 | } Unexecuted instantiation: Unified_cpp_image0.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<mozilla::image::IDecodingTask::NotifyProgress(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_1>(char const*, mozilla::image::IDecodingTask::NotifyProgress(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_1&&) Unexecuted instantiation: Unified_cpp_image0.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<mozilla::image::IDecodingTask::NotifyDecodeComplete(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_2>(char const*, mozilla::image::IDecodingTask::NotifyDecodeComplete(mozilla::NotNull<mozilla::image::RasterImage*>, mozilla::NotNull<mozilla::image::Decoder*>)::$_2&&) Unexecuted instantiation: Unified_cpp_image0.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<mozilla::image::ImageResource::SendOnUnlockedDraw(unsigned int)::$_3>(char const*, mozilla::image::ImageResource::SendOnUnlockedDraw(unsigned int)::$_3&&) Unexecuted instantiation: Unified_cpp_image1.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<mozilla::image::RasterImage::OnSurfaceDiscarded(mozilla::image::SurfaceKey const&)::$_8>(char const*, mozilla::image::RasterImage::OnSurfaceDiscarded(mozilla::image::SurfaceKey const&)::$_8&&) Unexecuted instantiation: Unified_cpp_image1.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<mozilla::image::VectorImage::SendFrameComplete(bool, unsigned int)::$_9>(char const*, mozilla::image::VectorImage::SendFrameComplete(bool, unsigned int)::$_9&&) Unexecuted instantiation: TelemetryCommon.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<mozilla::Telemetry::Common::LogToBrowserConsole(unsigned int, nsTSubstring<char16_t> const&)::$_0>(char const*, mozilla::Telemetry::Common::LogToBrowserConsole(unsigned int, nsTSubstring<char16_t> const&)::$_0&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<(anonymous namespace)::PersistenceThreadLoadData()::$_5::operator()() const::{lambda()#1}>(char const*, (anonymous namespace)::PersistenceThreadLoadData()::$_5::operator()() const::{lambda()#1}&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<(anonymous namespace)::MainThreadArmPersistenceTimer()::$_3::operator()(nsITimer*, void*) const::{lambda()#1}>(char const*, (anonymous namespace)::MainThreadArmPersistenceTimer()::$_3::operator()(nsITimer*, void*) const::{lambda()#1}&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<(anonymous namespace)::PersistenceThreadPersist()::$_4::operator()() const::{lambda()#1}>(char const*, (anonymous namespace)::PersistenceThreadPersist()::$_4::operator()() const::{lambda()#1}&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<TelemetryGeckoViewTesting::TestDispatchPersist()::$_0>(char const*, TelemetryGeckoViewTesting::TestDispatchPersist()::$_0&&) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:already_AddRefed<mozilla::Runnable> NS_NewRunnableFunction<TelemetryGeckoViewPersistence::ClearPersistenceData()::$_1>(char const*, TelemetryGeckoViewPersistence::ClearPersistenceData()::$_1&&) |
674 | | |
675 | | namespace mozilla { |
676 | | namespace detail { |
677 | | |
678 | | template <RunnableKind Kind> |
679 | | class TimerBehaviour |
680 | | { |
681 | | public: |
682 | | nsITimer* GetTimer() { return nullptr; } |
683 | | void CancelTimer() {} |
684 | | |
685 | | protected: |
686 | | ~TimerBehaviour() {} |
687 | | }; |
688 | | |
689 | | template <> |
690 | | class TimerBehaviour<RunnableKind::IdleWithTimer> |
691 | | { |
692 | | public: |
693 | | nsITimer* GetTimer() |
694 | | { |
695 | | if (!mTimer) { |
696 | | mTimer = NS_NewTimer(); |
697 | | } |
698 | | |
699 | | return mTimer; |
700 | | } |
701 | | |
702 | | void CancelTimer() |
703 | | { |
704 | | if (mTimer) { |
705 | | mTimer->Cancel(); |
706 | | } |
707 | | } |
708 | | |
709 | | protected: |
710 | | ~TimerBehaviour() |
711 | | { |
712 | | CancelTimer(); |
713 | | } |
714 | | private: |
715 | | nsCOMPtr<nsITimer> mTimer; |
716 | | }; |
717 | | |
718 | | } // namespace detail |
719 | | } // namespace mozilla |
720 | | |
721 | | // An event that can be used to call a method on a class. The class type must |
722 | | // support reference counting. This event supports Revoke for use |
723 | | // with nsRevocableEventPtr. |
724 | | template<class ClassType, |
725 | | typename ReturnType = void, |
726 | | bool Owning = true, |
727 | | mozilla::RunnableKind Kind = mozilla::RunnableKind::Standard> |
728 | | class nsRunnableMethod |
729 | | : public mozilla::Conditional<Kind == mozilla::RunnableKind::Standard, |
730 | | mozilla::Runnable, |
731 | | typename mozilla::Conditional< |
732 | | Kind == mozilla::RunnableKind::Cancelable, |
733 | | mozilla::CancelableRunnable, |
734 | | mozilla::IdleRunnable>::Type>::Type, |
735 | | protected mozilla::detail::TimerBehaviour<Kind> |
736 | | { |
737 | | using BaseType = typename mozilla::Conditional<Kind == mozilla::RunnableKind::Standard, |
738 | | mozilla::Runnable, |
739 | | typename mozilla::Conditional< |
740 | | Kind == mozilla::RunnableKind::Cancelable, |
741 | | mozilla::CancelableRunnable, |
742 | | mozilla::IdleRunnable>::Type>::Type; |
743 | | public: |
744 | 0 | nsRunnableMethod(const char* aName) : BaseType(aName) {} Unexecuted instantiation: nsRunnableMethod<mozilla::image::ProgressTracker, void, true, (mozilla::RunnableKind)0>::nsRunnableMethod(char const*) Unexecuted instantiation: Telemetry.cpp:nsRunnableMethod<(anonymous namespace)::nsFetchTelemetryData, void, true, (mozilla::RunnableKind)0>::nsRunnableMethod(char const*) |
745 | | |
746 | | virtual void Revoke() = 0; |
747 | | |
748 | | // These ReturnTypeEnforcer classes set up a blacklist for return types that |
749 | | // we know are not safe. The default ReturnTypeEnforcer compiles just fine but |
750 | | // already_AddRefed will not. |
751 | | template<typename OtherReturnType> |
752 | | class ReturnTypeEnforcer |
753 | | { |
754 | | public: |
755 | | typedef int ReturnTypeIsSafe; |
756 | | }; |
757 | | |
758 | | template<class T> |
759 | | class ReturnTypeEnforcer<already_AddRefed<T>> |
760 | | { |
761 | | // No ReturnTypeIsSafe makes this illegal! |
762 | | }; |
763 | | |
764 | | // Make sure this return type is safe. |
765 | | typedef typename ReturnTypeEnforcer<ReturnType>::ReturnTypeIsSafe check; |
766 | | }; |
767 | | |
768 | | template<class ClassType, bool Owning> |
769 | | struct nsRunnableMethodReceiver |
770 | | { |
771 | | RefPtr<ClassType> mObj; |
772 | 0 | explicit nsRunnableMethodReceiver(ClassType* aObj) : mObj(aObj) {} Unexecuted instantiation: nsRunnableMethodReceiver<mozilla::image::ProgressTracker, true>::nsRunnableMethodReceiver(mozilla::image::ProgressTracker*) Unexecuted instantiation: Telemetry.cpp:nsRunnableMethodReceiver<(anonymous namespace)::nsFetchTelemetryData, true>::nsRunnableMethodReceiver((anonymous namespace)::nsFetchTelemetryData*) |
773 | 0 | ~nsRunnableMethodReceiver() { Revoke(); } Unexecuted instantiation: nsRunnableMethodReceiver<mozilla::image::ProgressTracker, true>::~nsRunnableMethodReceiver() Unexecuted instantiation: Telemetry.cpp:nsRunnableMethodReceiver<(anonymous namespace)::nsFetchTelemetryData, true>::~nsRunnableMethodReceiver() |
774 | 0 | ClassType* Get() const { return mObj.get(); } Unexecuted instantiation: nsRunnableMethodReceiver<mozilla::image::ProgressTracker, true>::Get() const Unexecuted instantiation: Telemetry.cpp:nsRunnableMethodReceiver<(anonymous namespace)::nsFetchTelemetryData, true>::Get() const |
775 | 0 | void Revoke() { mObj = nullptr; } Unexecuted instantiation: nsRunnableMethodReceiver<mozilla::image::ProgressTracker, true>::Revoke() Unexecuted instantiation: Telemetry.cpp:nsRunnableMethodReceiver<(anonymous namespace)::nsFetchTelemetryData, true>::Revoke() |
776 | | }; |
777 | | |
778 | | template<class ClassType> |
779 | | struct nsRunnableMethodReceiver<ClassType, false> |
780 | | { |
781 | | ClassType* MOZ_NON_OWNING_REF mObj; |
782 | | explicit nsRunnableMethodReceiver(ClassType* aObj) : mObj(aObj) {} |
783 | | ClassType* Get() const { return mObj; } |
784 | | void Revoke() { mObj = nullptr; } |
785 | | }; |
786 | | |
787 | | static inline constexpr bool |
788 | | IsIdle(mozilla::RunnableKind aKind) |
789 | 0 | { |
790 | 0 | return aKind == mozilla::RunnableKind::Idle || |
791 | 0 | aKind == mozilla::RunnableKind::IdleWithTimer; |
792 | 0 | } Unexecuted instantiation: IdleTaskRunner.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: FileDescriptorSetChild.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: FileDescriptorSetParent.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: Unified_cpp_image0.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: Unified_cpp_image1.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: Telemetry.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: TelemetryCommon.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: TelemetryHistogram.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: TelemetryGeckoViewPersistence.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: CombinedStacks.cpp:IsIdle(mozilla::RunnableKind) Unexecuted instantiation: Unified_cpp_netwerk_test_gtest0.cpp:IsIdle(mozilla::RunnableKind) |
793 | | |
794 | | template<typename PtrType, typename Method, bool Owning, mozilla::RunnableKind Kind> |
795 | | struct nsRunnableMethodTraits; |
796 | | |
797 | | template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As> |
798 | | struct nsRunnableMethodTraits<PtrType, R(C::*)(As...), Owning, Kind> |
799 | | { |
800 | | typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; |
801 | | static_assert(mozilla::IsBaseOf<C, class_type>::value, |
802 | | "Stored class must inherit from method's class"); |
803 | | typedef R return_type; |
804 | | typedef nsRunnableMethod<C, R, Owning, Kind> base_type; |
805 | | static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; |
806 | | }; |
807 | | |
808 | | template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As> |
809 | | struct nsRunnableMethodTraits<PtrType, R(C::*)(As...) const, Owning, Kind> |
810 | | { |
811 | | typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; |
812 | | static_assert(mozilla::IsBaseOf<C, class_type>::value, |
813 | | "Stored class must inherit from method's class"); |
814 | | typedef R return_type; |
815 | | typedef nsRunnableMethod<C, R, Owning, Kind> base_type; |
816 | | static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; |
817 | | }; |
818 | | |
819 | | #ifdef NS_HAVE_STDCALL |
820 | | template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As> |
821 | | struct nsRunnableMethodTraits<PtrType, R(__stdcall C::*)(As...), Owning, Kind> |
822 | | { |
823 | | typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; |
824 | | static_assert(mozilla::IsBaseOf<C, class_type>::value, |
825 | | "Stored class must inherit from method's class"); |
826 | | typedef R return_type; |
827 | | typedef nsRunnableMethod<C, R, Owning, Kind> base_type; |
828 | | static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; |
829 | | }; |
830 | | |
831 | | template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind> |
832 | | struct nsRunnableMethodTraits<PtrType, R(NS_STDCALL C::*)(), Owning, Kind> |
833 | | { |
834 | | typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; |
835 | | static_assert(mozilla::IsBaseOf<C, class_type>::value, |
836 | | "Stored class must inherit from method's class"); |
837 | | typedef R return_type; |
838 | | typedef nsRunnableMethod<C, R, Owning, Kind> base_type; |
839 | | static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; |
840 | | }; |
841 | | |
842 | | template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As> |
843 | | struct nsRunnableMethodTraits<PtrType, R(__stdcall C::*)(As...) const, Owning, Kind> |
844 | | { |
845 | | typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; |
846 | | static_assert(mozilla::IsBaseOf<C, class_type>::value, |
847 | | "Stored class must inherit from method's class"); |
848 | | typedef R return_type; |
849 | | typedef nsRunnableMethod<C, R, Owning, Kind> base_type; |
850 | | static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; |
851 | | }; |
852 | | |
853 | | template<typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind> |
854 | | struct nsRunnableMethodTraits<PtrType, R(NS_STDCALL C::*)() const, Owning, Kind> |
855 | | { |
856 | | typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; |
857 | | static_assert(mozilla::IsBaseOf<C, class_type>::value, |
858 | | "Stored class must inherit from method's class"); |
859 | | typedef R return_type; |
860 | | typedef nsRunnableMethod<C, R, Owning, Kind> base_type; |
861 | | static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; |
862 | | }; |
863 | | #endif |
864 | | |
865 | | |
866 | | // IsParameterStorageClass<T>::value is true if T is a parameter-storage class |
867 | | // that will be recognized by NS_New[NonOwning]RunnableMethodWithArg[s] to |
868 | | // force a specific storage&passing strategy (instead of inferring one, |
869 | | // see ParameterStorage). |
870 | | // When creating a new storage class, add a specialization for it to be |
871 | | // recognized. |
872 | | template<typename T> |
873 | | struct IsParameterStorageClass : public mozilla::FalseType {}; |
874 | | |
875 | | // StoreXPassByY structs used to inform nsRunnableMethodArguments how to |
876 | | // store arguments, and how to pass them to the target method. |
877 | | |
878 | | template<typename T> |
879 | | struct StoreCopyPassByValue |
880 | | { |
881 | | typedef typename mozilla::Decay<T>::Type stored_type; |
882 | | typedef stored_type passed_type; |
883 | | stored_type m; |
884 | | template <typename A> |
885 | | MOZ_IMPLICIT StoreCopyPassByValue(A&& a) : m(std::forward<A>(a)) {} |
886 | | passed_type PassAsParameter() { return m; } |
887 | | }; |
888 | | template<typename S> |
889 | | struct IsParameterStorageClass<StoreCopyPassByValue<S>> |
890 | | : public mozilla::TrueType {}; |
891 | | |
892 | | template<typename T> |
893 | | struct StoreCopyPassByConstLRef |
894 | | { |
895 | | typedef typename mozilla::Decay<T>::Type stored_type; |
896 | | typedef const stored_type& passed_type; |
897 | | stored_type m; |
898 | | template <typename A> |
899 | | MOZ_IMPLICIT StoreCopyPassByConstLRef(A&& a) : m(std::forward<A>(a)) {} |
900 | | passed_type PassAsParameter() { return m; } |
901 | | }; |
902 | | template<typename S> |
903 | | struct IsParameterStorageClass<StoreCopyPassByConstLRef<S>> |
904 | | : public mozilla::TrueType {}; |
905 | | |
906 | | template<typename T> |
907 | | struct StoreCopyPassByLRef |
908 | | { |
909 | | typedef typename mozilla::Decay<T>::Type stored_type; |
910 | | typedef stored_type& passed_type; |
911 | | stored_type m; |
912 | | template <typename A> |
913 | | MOZ_IMPLICIT StoreCopyPassByLRef(A&& a) : m(std::forward<A>(a)) {} |
914 | | passed_type PassAsParameter() { return m; } |
915 | | }; |
916 | | template<typename S> |
917 | | struct IsParameterStorageClass<StoreCopyPassByLRef<S>> |
918 | | : public mozilla::TrueType {}; |
919 | | |
920 | | template<typename T> |
921 | | struct StoreCopyPassByRRef |
922 | | { |
923 | | typedef typename mozilla::Decay<T>::Type stored_type; |
924 | | typedef stored_type&& passed_type; |
925 | | stored_type m; |
926 | | template <typename A> |
927 | | MOZ_IMPLICIT StoreCopyPassByRRef(A&& a) : m(std::forward<A>(a)) {} |
928 | | passed_type PassAsParameter() { return std::move(m); } |
929 | | }; |
930 | | template<typename S> |
931 | | struct IsParameterStorageClass<StoreCopyPassByRRef<S>> |
932 | | : public mozilla::TrueType {}; |
933 | | |
934 | | template<typename T> |
935 | | struct StoreRefPassByLRef |
936 | | { |
937 | | typedef T& stored_type; |
938 | | typedef T& passed_type; |
939 | | stored_type m; |
940 | | template <typename A> |
941 | | MOZ_IMPLICIT StoreRefPassByLRef(A& a) : m(a) {} |
942 | | passed_type PassAsParameter() { return m; } |
943 | | }; |
944 | | template<typename S> |
945 | | struct IsParameterStorageClass<StoreRefPassByLRef<S>> |
946 | | : public mozilla::TrueType {}; |
947 | | |
948 | | template<typename T> |
949 | | struct StoreConstRefPassByConstLRef |
950 | | { |
951 | | typedef const T& stored_type; |
952 | | typedef const T& passed_type; |
953 | | stored_type m; |
954 | | template <typename A> |
955 | | MOZ_IMPLICIT StoreConstRefPassByConstLRef(const A& a) : m(a) {} |
956 | | passed_type PassAsParameter() { return m; } |
957 | | }; |
958 | | template<typename S> |
959 | | struct IsParameterStorageClass<StoreConstRefPassByConstLRef<S>> |
960 | | : public mozilla::TrueType {}; |
961 | | |
962 | | template<typename T> |
963 | | struct StoreRefPtrPassByPtr |
964 | | { |
965 | | typedef RefPtr<T> stored_type; |
966 | | typedef T* passed_type; |
967 | | stored_type m; |
968 | | template <typename A> |
969 | | MOZ_IMPLICIT StoreRefPtrPassByPtr(A&& a) : m(std::forward<A>(a)) {} |
970 | | passed_type PassAsParameter() { return m.get(); } |
971 | | }; |
972 | | template<typename S> |
973 | | struct IsParameterStorageClass<StoreRefPtrPassByPtr<S>> |
974 | | : public mozilla::TrueType {}; |
975 | | |
976 | | template<typename T> |
977 | | struct StorePtrPassByPtr |
978 | | { |
979 | | typedef T* stored_type; |
980 | | typedef T* passed_type; |
981 | | stored_type m; |
982 | | template <typename A> |
983 | | MOZ_IMPLICIT StorePtrPassByPtr(A a) : m(a) {} |
984 | | passed_type PassAsParameter() { return m; } |
985 | | }; |
986 | | template<typename S> |
987 | | struct IsParameterStorageClass<StorePtrPassByPtr<S>> |
988 | | : public mozilla::TrueType {}; |
989 | | |
990 | | template<typename T> |
991 | | struct StoreConstPtrPassByConstPtr |
992 | | { |
993 | | typedef const T* stored_type; |
994 | | typedef const T* passed_type; |
995 | | stored_type m; |
996 | | template <typename A> |
997 | | MOZ_IMPLICIT StoreConstPtrPassByConstPtr(A a) : m(a) {} |
998 | | passed_type PassAsParameter() { return m; } |
999 | | }; |
1000 | | template<typename S> |
1001 | | struct IsParameterStorageClass<StoreConstPtrPassByConstPtr<S>> |
1002 | | : public mozilla::TrueType {}; |
1003 | | |
1004 | | template<typename T> |
1005 | | struct StoreCopyPassByConstPtr |
1006 | | { |
1007 | | typedef T stored_type; |
1008 | | typedef const T* passed_type; |
1009 | | stored_type m; |
1010 | | template <typename A> |
1011 | | MOZ_IMPLICIT StoreCopyPassByConstPtr(A&& a) : m(std::forward<A>(a)) {} |
1012 | | passed_type PassAsParameter() { return &m; } |
1013 | | }; |
1014 | | template<typename S> |
1015 | | struct IsParameterStorageClass<StoreCopyPassByConstPtr<S>> |
1016 | | : public mozilla::TrueType {}; |
1017 | | |
1018 | | template<typename T> |
1019 | | struct StoreCopyPassByPtr |
1020 | | { |
1021 | | typedef T stored_type; |
1022 | | typedef T* passed_type; |
1023 | | stored_type m; |
1024 | | template <typename A> |
1025 | | MOZ_IMPLICIT StoreCopyPassByPtr(A&& a) : m(std::forward<A>(a)) {} |
1026 | | passed_type PassAsParameter() { return &m; } |
1027 | | }; |
1028 | | template<typename S> |
1029 | | struct IsParameterStorageClass<StoreCopyPassByPtr<S>> |
1030 | | : public mozilla::TrueType {}; |
1031 | | |
1032 | | namespace detail { |
1033 | | |
1034 | | template<typename> |
1035 | | struct SFINAE1True : mozilla::TrueType |
1036 | | {}; |
1037 | | |
1038 | | template<class T> |
1039 | | static auto HasRefCountMethodsTest(int) |
1040 | | -> SFINAE1True<decltype(mozilla::DeclVal<T>().AddRef(), |
1041 | | mozilla::DeclVal<T>().Release())>; |
1042 | | template<class> |
1043 | | static auto HasRefCountMethodsTest(long) -> mozilla::FalseType; |
1044 | | |
1045 | | template<class T> |
1046 | | struct HasRefCountMethods : decltype(HasRefCountMethodsTest<T>(0)) |
1047 | | {}; |
1048 | | |
1049 | | template<typename TWithoutPointer> |
1050 | | struct NonnsISupportsPointerStorageClass |
1051 | | : mozilla::Conditional<mozilla::IsConst<TWithoutPointer>::value, |
1052 | | StoreConstPtrPassByConstPtr< |
1053 | | typename mozilla::RemoveConst<TWithoutPointer>::Type>, |
1054 | | StorePtrPassByPtr<TWithoutPointer>> |
1055 | | {}; |
1056 | | |
1057 | | template<typename TWithoutPointer> |
1058 | | struct PointerStorageClass |
1059 | | : mozilla::Conditional<HasRefCountMethods<TWithoutPointer>::value, |
1060 | | StoreRefPtrPassByPtr<TWithoutPointer>, |
1061 | | typename NonnsISupportsPointerStorageClass< |
1062 | | TWithoutPointer |
1063 | | >::Type> |
1064 | | {}; |
1065 | | |
1066 | | template<typename TWithoutRef> |
1067 | | struct LValueReferenceStorageClass |
1068 | | : mozilla::Conditional<mozilla::IsConst<TWithoutRef>::value, |
1069 | | StoreConstRefPassByConstLRef< |
1070 | | typename mozilla::RemoveConst<TWithoutRef>::Type>, |
1071 | | StoreRefPassByLRef<TWithoutRef>> |
1072 | | {}; |
1073 | | |
1074 | | template<typename T> |
1075 | | struct SmartPointerStorageClass |
1076 | | : mozilla::Conditional<mozilla::IsRefcountedSmartPointer<T>::value, |
1077 | | StoreRefPtrPassByPtr< |
1078 | | typename mozilla::RemoveSmartPointer<T>::Type>, |
1079 | | StoreCopyPassByConstLRef<T>> |
1080 | | {}; |
1081 | | |
1082 | | template<typename T> |
1083 | | struct NonLValueReferenceStorageClass |
1084 | | : mozilla::Conditional<mozilla::IsRvalueReference<T>::value, |
1085 | | StoreCopyPassByRRef< |
1086 | | typename mozilla::RemoveReference<T>::Type>, |
1087 | | typename SmartPointerStorageClass<T>::Type> |
1088 | | {}; |
1089 | | |
1090 | | template<typename T> |
1091 | | struct NonPointerStorageClass |
1092 | | : mozilla::Conditional<mozilla::IsLvalueReference<T>::value, |
1093 | | typename LValueReferenceStorageClass< |
1094 | | typename mozilla::RemoveReference<T>::Type |
1095 | | >::Type, |
1096 | | typename NonLValueReferenceStorageClass<T>::Type> |
1097 | | {}; |
1098 | | |
1099 | | template<typename T> |
1100 | | struct NonParameterStorageClass |
1101 | | : mozilla::Conditional<mozilla::IsPointer<T>::value, |
1102 | | typename PointerStorageClass< |
1103 | | typename mozilla::RemovePointer<T>::Type |
1104 | | >::Type, |
1105 | | typename NonPointerStorageClass<T>::Type> |
1106 | | {}; |
1107 | | |
1108 | | // Choose storage&passing strategy based on preferred storage type: |
1109 | | // - If IsParameterStorageClass<T>::value is true, use as-is. |
1110 | | // - RC* -> StoreRefPtrPassByPtr<RC> : Store RefPtr<RC>, pass RC* |
1111 | | // ^^ RC quacks like a ref-counted type (i.e., has AddRef and Release methods) |
1112 | | // - const T* -> StoreConstPtrPassByConstPtr<T> : Store const T*, pass const T* |
1113 | | // - T* -> StorePtrPassByPtr<T> : Store T*, pass T*. |
1114 | | // - const T& -> StoreConstRefPassByConstLRef<T>: Store const T&, pass const T&. |
1115 | | // - T& -> StoreRefPassByLRef<T> : Store T&, pass T&. |
1116 | | // - T&& -> StoreCopyPassByRRef<T> : Store T, pass std::move(T). |
1117 | | // - RefPtr<T>, nsCOMPtr<T> |
1118 | | // -> StoreRefPtrPassByPtr<T> : Store RefPtr<T>, pass T* |
1119 | | // - Other T -> StoreCopyPassByConstLRef<T> : Store T, pass const T&. |
1120 | | // Other available explicit options: |
1121 | | // - StoreCopyPassByValue<T> : Store T, pass T. |
1122 | | // - StoreCopyPassByLRef<T> : Store T, pass T& (of copy!) |
1123 | | // - StoreCopyPassByConstPtr<T> : Store T, pass const T* |
1124 | | // - StoreCopyPassByPtr<T> : Store T, pass T* (of copy!) |
1125 | | // Or create your own class with PassAsParameter() method, optional |
1126 | | // clean-up in destructor, and with associated IsParameterStorageClass<>. |
1127 | | template<typename T> |
1128 | | struct ParameterStorage |
1129 | | : mozilla::Conditional<IsParameterStorageClass<T>::value, |
1130 | | T, |
1131 | | typename NonParameterStorageClass<T>::Type> |
1132 | | {}; |
1133 | | |
1134 | | template<class T> |
1135 | | static auto |
1136 | | HasSetDeadlineTest(int) -> SFINAE1True<decltype( |
1137 | | mozilla::DeclVal<T>().SetDeadline(mozilla::DeclVal<mozilla::TimeStamp>()))>; |
1138 | | |
1139 | | template<class T> |
1140 | | static auto |
1141 | | HasSetDeadlineTest(long) -> mozilla::FalseType; |
1142 | | |
1143 | | template<class T> |
1144 | | struct HasSetDeadline : decltype(HasSetDeadlineTest<T>(0)) |
1145 | | {}; |
1146 | | |
1147 | | template <class T> |
1148 | | typename mozilla::EnableIf<::detail::HasSetDeadline<T>::value>::Type |
1149 | | SetDeadlineImpl(T* aObj, mozilla::TimeStamp aTimeStamp) |
1150 | | { |
1151 | | aObj->SetDeadline(aTimeStamp); |
1152 | | } |
1153 | | |
1154 | | template <class T> |
1155 | | typename mozilla::EnableIf<!::detail::HasSetDeadline<T>::value>::Type |
1156 | | SetDeadlineImpl(T* aObj, mozilla::TimeStamp aTimeStamp) |
1157 | | { |
1158 | | } |
1159 | | } /* namespace detail */ |
1160 | | |
1161 | | namespace mozilla { |
1162 | | namespace detail { |
1163 | | |
1164 | | // struct used to store arguments and later apply them to a method. |
1165 | | template <typename... Ts> |
1166 | | struct RunnableMethodArguments final |
1167 | | { |
1168 | | Tuple<typename ::detail::ParameterStorage<Ts>::Type...> mArguments; |
1169 | | template <typename... As> |
1170 | | explicit RunnableMethodArguments(As&&... aArguments) |
1171 | | : mArguments(std::forward<As>(aArguments)...) |
1172 | | {} |
1173 | | template<typename C, typename M, typename... Args, size_t... Indices> |
1174 | | static auto |
1175 | | applyImpl(C* o, M m, Tuple<Args...>& args, std::index_sequence<Indices...>) |
1176 | | -> decltype(((*o).*m)(Get<Indices>(args).PassAsParameter()...)) |
1177 | 0 | { |
1178 | 0 | return ((*o).*m)(Get<Indices>(args).PassAsParameter()...); |
1179 | 0 | } Unexecuted instantiation: decltype (((*{parm#1}).*{parm#2})()) mozilla::detail::RunnableMethodArguments<>::applyImpl<mozilla::image::ProgressTracker, void (mozilla::image::ProgressTracker::*)()>(mozilla::image::ProgressTracker*, void (mozilla::image::ProgressTracker::*)(), mozilla::Tuple<>&, std::__1::integer_sequence<unsigned long>) Unexecuted instantiation: Telemetry.cpp:decltype (((*{parm#1}).*{parm#2})()) mozilla::detail::RunnableMethodArguments<>::applyImpl<(anonymous namespace)::nsFetchTelemetryData, void ((anonymous namespace)::nsFetchTelemetryData::*)()>((anonymous namespace)::nsFetchTelemetryData*, void ((anonymous namespace)::nsFetchTelemetryData::*)(), mozilla::Tuple<>&, std::__1::integer_sequence<unsigned long>) |
1180 | | template<class C, typename M> auto apply(C* o, M m) |
1181 | | -> decltype(applyImpl(o, m, mArguments, |
1182 | | std::index_sequence_for<Ts...>{})) |
1183 | 0 | { |
1184 | 0 | return applyImpl(o, m, mArguments, |
1185 | 0 | std::index_sequence_for<Ts...>{}); |
1186 | 0 | } Unexecuted instantiation: _ZN7mozilla6detail23RunnableMethodArgumentsIJEE5applyINS_5image15ProgressTrackerEMS5_FvvEEEDTcl9applyImplfp_fp0_dtdefpT10mArgumentstlNSt3__116integer_sequenceImJEEEEEEPT_T0_ Unexecuted instantiation: Telemetry.cpp:_ZN7mozilla6detail23RunnableMethodArgumentsIJEE5applyIN12_GLOBAL__N_120nsFetchTelemetryDataEMS5_FvvEEEDTcl9applyImplfp_fp0_dtdefpT10mArgumentstlNSt3__116integer_sequenceImJEEEEEEPT_T0_ |
1187 | | }; |
1188 | | |
1189 | | template<typename PtrType, typename Method, bool Owning, RunnableKind Kind, typename... Storages> |
1190 | | class RunnableMethodImpl final |
1191 | | : public ::nsRunnableMethodTraits<PtrType, Method, Owning, Kind>::base_type |
1192 | | { |
1193 | | typedef typename ::nsRunnableMethodTraits<PtrType, Method, Owning, Kind> Traits; |
1194 | | |
1195 | | typedef typename Traits::class_type ClassType; |
1196 | | typedef typename Traits::base_type BaseType; |
1197 | | ::nsRunnableMethodReceiver<ClassType, Owning> mReceiver; |
1198 | | Method mMethod; |
1199 | | RunnableMethodArguments<Storages...> mArgs; |
1200 | | using BaseType::GetTimer; |
1201 | | using BaseType::CancelTimer; |
1202 | | private: |
1203 | 0 | virtual ~RunnableMethodImpl() { Revoke(); }; Unexecuted instantiation: mozilla::detail::RunnableMethodImpl<RefPtr<mozilla::image::ProgressTracker>, void (mozilla::image::ProgressTracker::*)(), true, (mozilla::RunnableKind)0>::~RunnableMethodImpl() Unexecuted instantiation: Telemetry.cpp:mozilla::detail::RunnableMethodImpl<(anonymous namespace)::nsFetchTelemetryData*, void ((anonymous namespace)::nsFetchTelemetryData::*)(), true, (mozilla::RunnableKind)0>::~RunnableMethodImpl() |
1204 | | static void TimedOut(nsITimer* aTimer, void* aClosure) |
1205 | | { |
1206 | | static_assert(IsIdle(Kind), "Don't use me!"); |
1207 | | RefPtr<IdleRunnable> r = static_cast<IdleRunnable*>(aClosure); |
1208 | | r->SetDeadline(TimeStamp()); |
1209 | | r->Run(); |
1210 | | r->Cancel(); |
1211 | | } |
1212 | | public: |
1213 | | template<typename ForwardedPtrType, typename... Args> |
1214 | | explicit RunnableMethodImpl(const char* aName, ForwardedPtrType&& aObj, |
1215 | | Method aMethod, Args&&... aArgs) |
1216 | | : BaseType(aName) |
1217 | | , mReceiver(std::forward<ForwardedPtrType>(aObj)) |
1218 | | , mMethod(aMethod) |
1219 | | , mArgs(std::forward<Args>(aArgs)...) |
1220 | 0 | { |
1221 | 0 | static_assert(sizeof...(Storages) == sizeof...(Args), "Storages and Args should have equal sizes"); |
1222 | 0 | } Unexecuted instantiation: mozilla::detail::RunnableMethodImpl<RefPtr<mozilla::image::ProgressTracker>, void (mozilla::image::ProgressTracker::*)(), true, (mozilla::RunnableKind)0>::RunnableMethodImpl<RefPtr<mozilla::image::ProgressTracker>&>(char const*, RefPtr<mozilla::image::ProgressTracker>&, void (mozilla::image::ProgressTracker::*)()) Unexecuted instantiation: Telemetry.cpp:mozilla::detail::RunnableMethodImpl<(anonymous namespace)::nsFetchTelemetryData*, void ((anonymous namespace)::nsFetchTelemetryData::*)(), true, (mozilla::RunnableKind)0>::RunnableMethodImpl<(anonymous namespace)::nsFetchTelemetryData*>(char const*, (anonymous namespace)::nsFetchTelemetryData*&&, void ((anonymous namespace)::nsFetchTelemetryData::*)()) |
1223 | | |
1224 | | NS_IMETHOD Run() |
1225 | 0 | { |
1226 | 0 | CancelTimer(); |
1227 | 0 |
|
1228 | 0 | if (MOZ_LIKELY(mReceiver.Get())) { |
1229 | 0 | mArgs.apply(mReceiver.Get(), mMethod); |
1230 | 0 | } |
1231 | 0 |
|
1232 | 0 | return NS_OK; |
1233 | 0 | } Unexecuted instantiation: mozilla::detail::RunnableMethodImpl<RefPtr<mozilla::image::ProgressTracker>, void (mozilla::image::ProgressTracker::*)(), true, (mozilla::RunnableKind)0>::Run() Unexecuted instantiation: Telemetry.cpp:mozilla::detail::RunnableMethodImpl<(anonymous namespace)::nsFetchTelemetryData*, void ((anonymous namespace)::nsFetchTelemetryData::*)(), true, (mozilla::RunnableKind)0>::Run() |
1234 | | |
1235 | | nsresult Cancel() |
1236 | | { |
1237 | | static_assert(Kind >= RunnableKind::Cancelable, "Don't use me!"); |
1238 | | Revoke(); |
1239 | | return NS_OK; |
1240 | | } |
1241 | | |
1242 | | void Revoke() |
1243 | 0 | { |
1244 | 0 | CancelTimer(); |
1245 | 0 | mReceiver.Revoke(); |
1246 | 0 | } Unexecuted instantiation: mozilla::detail::RunnableMethodImpl<RefPtr<mozilla::image::ProgressTracker>, void (mozilla::image::ProgressTracker::*)(), true, (mozilla::RunnableKind)0>::Revoke() Unexecuted instantiation: Telemetry.cpp:mozilla::detail::RunnableMethodImpl<(anonymous namespace)::nsFetchTelemetryData*, void ((anonymous namespace)::nsFetchTelemetryData::*)(), true, (mozilla::RunnableKind)0>::Revoke() |
1247 | | |
1248 | | void SetDeadline(TimeStamp aDeadline) |
1249 | | { |
1250 | | if (MOZ_LIKELY(mReceiver.Get())) { |
1251 | | ::detail::SetDeadlineImpl(mReceiver.Get(), aDeadline); |
1252 | | } |
1253 | | } |
1254 | | |
1255 | | void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) |
1256 | | { |
1257 | | MOZ_ASSERT(aTarget); |
1258 | | |
1259 | | if (nsCOMPtr<nsITimer> timer = GetTimer()) { |
1260 | | timer->Cancel(); |
1261 | | timer->SetTarget(aTarget); |
1262 | | timer->InitWithNamedFuncCallback(TimedOut, |
1263 | | this, |
1264 | | aDelay, |
1265 | | nsITimer::TYPE_ONE_SHOT, |
1266 | | "detail::RunnableMethodImpl::SetTimer"); |
1267 | | } |
1268 | | } |
1269 | | }; |
1270 | | |
1271 | | // Type aliases for NewRunnableMethod. |
1272 | | template<typename PtrType, typename Method> |
1273 | | using OwningRunnableMethod = typename ::nsRunnableMethodTraits< |
1274 | | typename RemoveReference<PtrType>::Type, Method, true, RunnableKind::Standard>::base_type; |
1275 | | template<typename PtrType, typename Method, typename... Storages> |
1276 | | using OwningRunnableMethodImpl = RunnableMethodImpl< |
1277 | | typename RemoveReference<PtrType>::Type, Method, true, RunnableKind::Standard, Storages...>; |
1278 | | |
1279 | | // Type aliases for NewCancelableRunnableMethod. |
1280 | | template<typename PtrType, typename Method> |
1281 | | using CancelableRunnableMethod = typename ::nsRunnableMethodTraits< |
1282 | | typename RemoveReference<PtrType>::Type, Method, true, RunnableKind::Cancelable>::base_type; |
1283 | | template<typename PtrType, typename Method, typename... Storages> |
1284 | | using CancelableRunnableMethodImpl = RunnableMethodImpl< |
1285 | | typename RemoveReference<PtrType>::Type, Method, true, RunnableKind::Cancelable, Storages...>; |
1286 | | |
1287 | | // Type aliases for NewIdleRunnableMethod. |
1288 | | template<typename PtrType, typename Method> |
1289 | | using IdleRunnableMethod = typename ::nsRunnableMethodTraits< |
1290 | | typename RemoveReference<PtrType>::Type, Method, true, RunnableKind::Idle>::base_type; |
1291 | | template<typename PtrType, typename Method, typename... Storages> |
1292 | | using IdleRunnableMethodImpl = RunnableMethodImpl< |
1293 | | typename RemoveReference<PtrType>::Type, Method, true, RunnableKind::Idle, Storages...>; |
1294 | | |
1295 | | // Type aliases for NewIdleRunnableMethodWithTimer. |
1296 | | template<typename PtrType, typename Method> |
1297 | | using IdleRunnableMethodWithTimer = typename ::nsRunnableMethodTraits< |
1298 | | typename RemoveReference<PtrType>::Type, Method, true, RunnableKind::IdleWithTimer>::base_type; |
1299 | | template<typename PtrType, typename Method, typename... Storages> |
1300 | | using IdleRunnableMethodWithTimerImpl = RunnableMethodImpl< |
1301 | | typename RemoveReference<PtrType>::Type, Method, true, RunnableKind::IdleWithTimer, Storages...>; |
1302 | | |
1303 | | // Type aliases for NewNonOwningRunnableMethod. |
1304 | | template<typename PtrType, typename Method> |
1305 | | using NonOwningRunnableMethod = typename ::nsRunnableMethodTraits< |
1306 | | typename RemoveReference<PtrType>::Type, Method, false, RunnableKind::Standard>::base_type; |
1307 | | template<typename PtrType, typename Method, typename... Storages> |
1308 | | using NonOwningRunnableMethodImpl = RunnableMethodImpl< |
1309 | | typename RemoveReference<PtrType>::Type, Method, false, RunnableKind::Standard, Storages...>; |
1310 | | |
1311 | | // Type aliases for NonOwningCancelableRunnableMethod |
1312 | | template<typename PtrType, typename Method> |
1313 | | using NonOwningCancelableRunnableMethod = typename ::nsRunnableMethodTraits< |
1314 | | typename RemoveReference<PtrType>::Type, Method, false, RunnableKind::Cancelable>::base_type; |
1315 | | template<typename PtrType, typename Method, typename... Storages> |
1316 | | using NonOwningCancelableRunnableMethodImpl = RunnableMethodImpl< |
1317 | | typename RemoveReference<PtrType>::Type, Method, false, RunnableKind::Cancelable, Storages...>; |
1318 | | |
1319 | | // Type aliases for NonOwningIdleRunnableMethod |
1320 | | template<typename PtrType, typename Method> |
1321 | | using NonOwningIdleRunnableMethod = typename ::nsRunnableMethodTraits< |
1322 | | typename RemoveReference<PtrType>::Type, Method, false, RunnableKind::Idle>::base_type; |
1323 | | template<typename PtrType, typename Method, typename... Storages> |
1324 | | using NonOwningIdleRunnableMethodImpl = RunnableMethodImpl< |
1325 | | typename RemoveReference<PtrType>::Type, Method, false, RunnableKind::Idle, Storages...>; |
1326 | | |
1327 | | // Type aliases for NewIdleRunnableMethodWithTimer. |
1328 | | template<typename PtrType, typename Method> |
1329 | | using NonOwningIdleRunnableMethodWithTimer = typename ::nsRunnableMethodTraits< |
1330 | | typename RemoveReference<PtrType>::Type, Method, false, RunnableKind::IdleWithTimer>::base_type; |
1331 | | template<typename PtrType, typename Method, typename... Storages> |
1332 | | using NonOwningIdleRunnableMethodWithTimerImpl = RunnableMethodImpl< |
1333 | | typename RemoveReference<PtrType>::Type, Method, false, RunnableKind::IdleWithTimer, Storages...>; |
1334 | | |
1335 | | } // namespace detail |
1336 | | |
1337 | | // NewRunnableMethod and friends |
1338 | | // |
1339 | | // Very often in Gecko, you'll find yourself in a situation where you want |
1340 | | // to invoke a method (with or without arguments) asynchronously. You |
1341 | | // could write a small helper class inheriting from nsRunnable to handle |
1342 | | // all these details, or you could let NewRunnableMethod take care of all |
1343 | | // those details for you. |
1344 | | // |
1345 | | // The simplest use of NewRunnableMethod looks like: |
1346 | | // |
1347 | | // nsCOMPtr<nsIRunnable> event = |
1348 | | // mozilla::NewRunnableMethod("description", myObject, &MyClass::HandleEvent); |
1349 | | // NS_DispatchToCurrentThread(event); |
1350 | | // |
1351 | | // Statically enforced constraints: |
1352 | | // - myObject must be of (or implicitly convertible to) type MyClass |
1353 | | // - MyClass must define AddRef and Release methods |
1354 | | // |
1355 | | // The "description" string should specify a human-readable name for the |
1356 | | // runnable; the provided string is used by various introspection tools |
1357 | | // in the browser. |
1358 | | // |
1359 | | // The created runnable will take a strong reference to `myObject`. For |
1360 | | // non-refcounted objects, or refcounted objects with unusual refcounting |
1361 | | // requirements, and if and only if you are 110% certain that `myObject` |
1362 | | // will live long enough, you can use NewNonOwningRunnableMethod instead, |
1363 | | // which will, as its name implies, take a non-owning reference. If you |
1364 | | // find yourself having to use this function, you should accompany your use |
1365 | | // with a proof comment describing why the runnable will not lead to |
1366 | | // use-after-frees. |
1367 | | // |
1368 | | // (If you find yourself writing contorted code to Release() an object |
1369 | | // asynchronously on a different thread, you should use the |
1370 | | // NS_ProxyRelease function.) |
1371 | | // |
1372 | | // Invoking a method with arguments takes a little more care. The |
1373 | | // natural extension of the above: |
1374 | | // |
1375 | | // nsCOMPtr<nsIRunnable> event = |
1376 | | // mozilla::NewRunnableMethod("description", myObject, &MyClass::HandleEvent, |
1377 | | // arg1, arg2, ...); |
1378 | | // |
1379 | | // can lead to security hazards (e.g. passing in raw pointers to refcounted |
1380 | | // objects and storing those raw pointers in the runnable). We therefore |
1381 | | // require you to specify the storage types used by the runnable, just as |
1382 | | // you would if you were writing out the class by hand: |
1383 | | // |
1384 | | // nsCOMPtr<nsIRunnable> event = |
1385 | | // mozilla::NewRunnableMethod<RefPtr<T>, nsTArray<U>> |
1386 | | // ("description", myObject, &MyClass::HandleEvent, arg1, arg2); |
1387 | | // |
1388 | | // Please note that you do not have to pass the same argument type as you |
1389 | | // specify in the template arguments. For example, if you want to transfer |
1390 | | // ownership to a runnable, you can write: |
1391 | | // |
1392 | | // RefPtr<T> ptr = ...; |
1393 | | // nsTArray<U> array = ...; |
1394 | | // nsCOMPtr<nsIRunnable> event = |
1395 | | // mozilla::NewRunnableMethod<RefPtr<T>, nsTArray<U>> |
1396 | | // ("description", myObject, &MyClass::DoSomething, |
1397 | | // std::move(ptr), std::move(array)); |
1398 | | // |
1399 | | // and there will be no extra AddRef/Release traffic, or copying of the array. |
1400 | | // |
1401 | | // Each type that you specify as a template argument to NewRunnableMethod |
1402 | | // comes with its own style of storage in the runnable and its own style |
1403 | | // of argument passing to the invoked method. See the comment for |
1404 | | // ParameterStorage above for more details. |
1405 | | // |
1406 | | // If you need to customize the storage type and/or argument passing type, |
1407 | | // you can write your own class to use as a template argument to |
1408 | | // NewRunnableMethod. If you find yourself having to do that frequently, |
1409 | | // please file a bug in Core::XPCOM about adding the custom type to the |
1410 | | // core code in this file, and/or for custom rules for ParameterStorage |
1411 | | // to select that strategy. |
1412 | | // |
1413 | | // For places that require you to use cancelable runnables, such as |
1414 | | // workers, there's also NewCancelableRunnableMethod and its non-owning |
1415 | | // counterpart. The runnables returned by these methods additionally |
1416 | | // implement nsICancelableRunnable. |
1417 | | // |
1418 | | // Finally, all of the functions discussed above have additional overloads |
1419 | | // that do not take a `const char*` as their first parameter; you may see |
1420 | | // these in older code. The `const char*` overload is preferred and |
1421 | | // should be used in new code exclusively. |
1422 | | |
1423 | | template<typename PtrType, typename Method> |
1424 | | already_AddRefed<detail::OwningRunnableMethod<PtrType, Method>> |
1425 | | NewRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod) |
1426 | 0 | { |
1427 | 0 | return do_AddRef( |
1428 | 0 | new detail::OwningRunnableMethodImpl<PtrType, Method>( |
1429 | 0 | aName, std::forward<PtrType>(aPtr), aMethod)); |
1430 | 0 | } Unexecuted instantiation: already_AddRefed<nsRunnableMethodTraits<mozilla::RemoveReference<RefPtr<mozilla::image::ProgressTracker>&>::Type, void (mozilla::image::ProgressTracker::*)(), true, (mozilla::RunnableKind)0>::base_type> mozilla::NewRunnableMethod<RefPtr<mozilla::image::ProgressTracker>&, void (mozilla::image::ProgressTracker::*)()>(char const*, RefPtr<mozilla::image::ProgressTracker>&, void (mozilla::image::ProgressTracker::*)()) Unexecuted instantiation: Telemetry.cpp:already_AddRefed<nsRunnableMethodTraits<mozilla::RemoveReference<(anonymous namespace)::nsFetchTelemetryData*>::Type, void ((anonymous namespace)::nsFetchTelemetryData::*)(), true, (mozilla::RunnableKind)0>::base_type> mozilla::NewRunnableMethod<(anonymous namespace)::nsFetchTelemetryData*, void ((anonymous namespace)::nsFetchTelemetryData::*)()>(char const*, (anonymous namespace)::nsFetchTelemetryData*&&, void ((anonymous namespace)::nsFetchTelemetryData::*)()) |
1431 | | |
1432 | | template<typename PtrType, typename Method> |
1433 | | already_AddRefed<detail::CancelableRunnableMethod<PtrType, Method>> |
1434 | | NewCancelableRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod) |
1435 | | { |
1436 | | return do_AddRef( |
1437 | | new detail::CancelableRunnableMethodImpl<PtrType, Method>( |
1438 | | aName, std::forward<PtrType>(aPtr), aMethod)); |
1439 | | } |
1440 | | |
1441 | | template<typename PtrType, typename Method> |
1442 | | already_AddRefed<detail::IdleRunnableMethod<PtrType, Method>> |
1443 | | NewIdleRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod) |
1444 | | { |
1445 | | return do_AddRef( |
1446 | | new detail::IdleRunnableMethodImpl<PtrType, Method>( |
1447 | | aName, std::forward<PtrType>(aPtr), aMethod)); |
1448 | | } |
1449 | | |
1450 | | template<typename PtrType, typename Method> |
1451 | | already_AddRefed<detail::IdleRunnableMethodWithTimer<PtrType, Method>> |
1452 | | NewIdleRunnableMethodWithTimer(const char* aName, |
1453 | | PtrType&& aPtr, |
1454 | | Method aMethod) |
1455 | | { |
1456 | | return do_AddRef( |
1457 | | new detail::IdleRunnableMethodWithTimerImpl<PtrType, Method>( |
1458 | | aName, std::forward<PtrType>(aPtr), aMethod)); |
1459 | | } |
1460 | | |
1461 | | template<typename PtrType, typename Method> |
1462 | | already_AddRefed<detail::NonOwningRunnableMethod<PtrType, Method>> |
1463 | | NewNonOwningRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod) |
1464 | | { |
1465 | | return do_AddRef( |
1466 | | new detail::NonOwningRunnableMethodImpl<PtrType, Method>( |
1467 | | aName, std::forward<PtrType>(aPtr), aMethod)); |
1468 | | } |
1469 | | |
1470 | | template<typename PtrType, typename Method> |
1471 | | already_AddRefed<detail::NonOwningCancelableRunnableMethod<PtrType, Method>> |
1472 | | NewNonOwningCancelableRunnableMethod(const char* aName, PtrType&& aPtr, |
1473 | | Method aMethod) |
1474 | | { |
1475 | | return do_AddRef( |
1476 | | new detail::NonOwningCancelableRunnableMethodImpl<PtrType, Method>( |
1477 | | aName, std::forward<PtrType>(aPtr), aMethod)); |
1478 | | } |
1479 | | |
1480 | | template<typename PtrType, typename Method> |
1481 | | already_AddRefed<detail::NonOwningIdleRunnableMethod<PtrType, Method>> |
1482 | | NewNonOwningIdleRunnableMethod(const char* aName, |
1483 | | PtrType&& aPtr, |
1484 | | Method aMethod) |
1485 | | { |
1486 | | return do_AddRef( |
1487 | | new detail::NonOwningIdleRunnableMethodImpl<PtrType, Method>( |
1488 | | aName, std::forward<PtrType>(aPtr), aMethod)); |
1489 | | } |
1490 | | |
1491 | | template<typename PtrType, typename Method> |
1492 | | already_AddRefed<detail::NonOwningIdleRunnableMethodWithTimer<PtrType, Method>> |
1493 | | NewNonOwningIdleRunnableMethodWithTimer(const char* aName, |
1494 | | PtrType&& aPtr, |
1495 | | Method aMethod) |
1496 | | { |
1497 | | return do_AddRef( |
1498 | | new detail::NonOwningIdleRunnableMethodWithTimerImpl<PtrType, Method>( |
1499 | | aName, std::forward<PtrType>(aPtr), aMethod)); |
1500 | | } |
1501 | | |
1502 | | // Similar to NewRunnableMethod. Call like so: |
1503 | | // nsCOMPtr<nsIRunnable> event = |
1504 | | // NewRunnableMethod<Types,...>(myObject, &MyClass::HandleEvent, myArg1,...); |
1505 | | // 'Types' are the stored type for each argument, see ParameterStorage for details. |
1506 | | template<typename... Storages, typename PtrType, typename Method, typename... Args> |
1507 | | already_AddRefed<detail::OwningRunnableMethod<PtrType, Method>> |
1508 | | NewRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod, Args&&... aArgs) |
1509 | | { |
1510 | | static_assert(sizeof...(Storages) == sizeof...(Args), |
1511 | | "<Storages...> size should be equal to number of arguments"); |
1512 | | return do_AddRef( |
1513 | | new detail::OwningRunnableMethodImpl<PtrType, Method, Storages...>( |
1514 | | aName, std::forward<PtrType>(aPtr), aMethod, std::forward<Args>(aArgs)...)); |
1515 | | } |
1516 | | |
1517 | | template<typename... Storages, typename PtrType, typename Method, typename... Args> |
1518 | | already_AddRefed<detail::NonOwningRunnableMethod<PtrType, Method>> |
1519 | | NewNonOwningRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod, |
1520 | | Args&&... aArgs) |
1521 | | { |
1522 | | static_assert(sizeof...(Storages) == sizeof...(Args), |
1523 | | "<Storages...> size should be equal to number of arguments"); |
1524 | | return do_AddRef( |
1525 | | new detail::NonOwningRunnableMethodImpl<PtrType, Method, Storages...>( |
1526 | | aName, std::forward<PtrType>(aPtr), aMethod, std::forward<Args>(aArgs)...)); |
1527 | | } |
1528 | | |
1529 | | template<typename... Storages, typename PtrType, typename Method, typename... Args> |
1530 | | already_AddRefed<detail::CancelableRunnableMethod<PtrType, Method>> |
1531 | | NewCancelableRunnableMethod(const char* aName, PtrType&& aPtr, Method aMethod, |
1532 | | Args&&... aArgs) |
1533 | | { |
1534 | | static_assert(sizeof...(Storages) == sizeof...(Args), |
1535 | | "<Storages...> size should be equal to number of arguments"); |
1536 | | return do_AddRef( |
1537 | | new detail::CancelableRunnableMethodImpl<PtrType, Method, Storages...>( |
1538 | | aName, std::forward<PtrType>(aPtr), aMethod, std::forward<Args>(aArgs)...)); |
1539 | | } |
1540 | | |
1541 | | template<typename... Storages, typename PtrType, typename Method, typename... Args> |
1542 | | already_AddRefed<detail::NonOwningCancelableRunnableMethod<PtrType, Method>> |
1543 | | NewNonOwningCancelableRunnableMethod(const char* aName, PtrType&& aPtr, |
1544 | | Method aMethod, Args&&... aArgs) |
1545 | | { |
1546 | | static_assert(sizeof...(Storages) == sizeof...(Args), |
1547 | | "<Storages...> size should be equal to number of arguments"); |
1548 | | return do_AddRef( |
1549 | | new detail::NonOwningCancelableRunnableMethodImpl<PtrType, Method, Storages...>( |
1550 | | aName, std::forward<PtrType>(aPtr), aMethod, std::forward<Args>(aArgs)...)); |
1551 | | } |
1552 | | |
1553 | | template<typename... Storages, |
1554 | | typename PtrType, |
1555 | | typename Method, |
1556 | | typename... Args> |
1557 | | already_AddRefed<detail::IdleRunnableMethod<PtrType, Method>> |
1558 | | NewIdleRunnableMethod(const char* aName, |
1559 | | PtrType&& aPtr, |
1560 | | Method aMethod, |
1561 | | Args&&... aArgs) |
1562 | | { |
1563 | | static_assert(sizeof...(Storages) == sizeof...(Args), |
1564 | | "<Storages...> size should be equal to number of arguments"); |
1565 | | return do_AddRef( |
1566 | | new detail::IdleRunnableMethodImpl<PtrType, Method, Storages...>( |
1567 | | aName, std::forward<PtrType>(aPtr), aMethod, std::forward<Args>(aArgs)...)); |
1568 | | } |
1569 | | |
1570 | | template<typename... Storages, |
1571 | | typename PtrType, |
1572 | | typename Method, |
1573 | | typename... Args> |
1574 | | already_AddRefed<detail::NonOwningIdleRunnableMethod<PtrType, Method>> |
1575 | | NewNonOwningIdleRunnableMethod(const char* aName, |
1576 | | PtrType&& aPtr, |
1577 | | Method aMethod, |
1578 | | Args&&... aArgs) |
1579 | | { |
1580 | | static_assert(sizeof...(Storages) == sizeof...(Args), |
1581 | | "<Storages...> size should be equal to number of arguments"); |
1582 | | return do_AddRef( |
1583 | | new detail::NonOwningIdleRunnableMethodImpl<PtrType, Method, Storages...>( |
1584 | | aName, std::forward<PtrType>(aPtr), aMethod, std::forward<Args>(aArgs)...)); |
1585 | | } |
1586 | | |
1587 | | } // namespace mozilla |
1588 | | |
1589 | | #endif // XPCOM_GLUE_AVOID_NSPR |
1590 | | |
1591 | | // This class is designed to be used when you have an event class E that has a |
1592 | | // pointer back to resource class R. If R goes away while E is still pending, |
1593 | | // then it is important to "revoke" E so that it does not try use R after R has |
1594 | | // been destroyed. nsRevocableEventPtr makes it easy for R to manage such |
1595 | | // situations: |
1596 | | // |
1597 | | // class R; |
1598 | | // |
1599 | | // class E : public mozilla::Runnable { |
1600 | | // public: |
1601 | | // void Revoke() { |
1602 | | // mResource = nullptr; |
1603 | | // } |
1604 | | // private: |
1605 | | // R *mResource; |
1606 | | // }; |
1607 | | // |
1608 | | // class R { |
1609 | | // public: |
1610 | | // void EventHandled() { |
1611 | | // mEvent.Forget(); |
1612 | | // } |
1613 | | // private: |
1614 | | // nsRevocableEventPtr<E> mEvent; |
1615 | | // }; |
1616 | | // |
1617 | | // void R::PostEvent() { |
1618 | | // // Make sure any pending event is revoked. |
1619 | | // mEvent->Revoke(); |
1620 | | // |
1621 | | // nsCOMPtr<nsIRunnable> event = new E(); |
1622 | | // if (NS_SUCCEEDED(NS_DispatchToCurrentThread(event))) { |
1623 | | // // Keep pointer to event so we can revoke it. |
1624 | | // mEvent = event; |
1625 | | // } |
1626 | | // } |
1627 | | // |
1628 | | // NS_IMETHODIMP E::Run() { |
1629 | | // if (!mResource) |
1630 | | // return NS_OK; |
1631 | | // ... |
1632 | | // mResource->EventHandled(); |
1633 | | // return NS_OK; |
1634 | | // } |
1635 | | // |
1636 | | template<class T> |
1637 | | class nsRevocableEventPtr |
1638 | | { |
1639 | | public: |
1640 | | nsRevocableEventPtr() : mEvent(nullptr) {} |
1641 | | ~nsRevocableEventPtr() { Revoke(); } |
1642 | | |
1643 | | const nsRevocableEventPtr& operator=(RefPtr<T>&& aEvent) |
1644 | | { |
1645 | | if (mEvent != aEvent) { |
1646 | | Revoke(); |
1647 | | mEvent = std::move(aEvent); |
1648 | | } |
1649 | | return *this; |
1650 | | } |
1651 | | |
1652 | | void Revoke() |
1653 | | { |
1654 | | if (mEvent) { |
1655 | | mEvent->Revoke(); |
1656 | | mEvent = nullptr; |
1657 | | } |
1658 | | } |
1659 | | |
1660 | | void Forget() { mEvent = nullptr; } |
1661 | | bool IsPending() { return mEvent != nullptr; } |
1662 | | T* get() { return mEvent; } |
1663 | | |
1664 | | private: |
1665 | | // Not implemented |
1666 | | nsRevocableEventPtr(const nsRevocableEventPtr&); |
1667 | | nsRevocableEventPtr& operator=(const nsRevocableEventPtr&); |
1668 | | |
1669 | | RefPtr<T> mEvent; |
1670 | | }; |
1671 | | |
1672 | | template <class T> |
1673 | | inline already_AddRefed<T> |
1674 | | do_AddRef(nsRevocableEventPtr<T>& aObj) |
1675 | | { |
1676 | | return do_AddRef(aObj.get()); |
1677 | | } |
1678 | | |
1679 | | /** |
1680 | | * A simple helper to suffix thread pool name |
1681 | | * with incremental numbers. |
1682 | | */ |
1683 | | class nsThreadPoolNaming |
1684 | | { |
1685 | | public: |
1686 | | nsThreadPoolNaming() : mCounter(0) {} |
1687 | | |
1688 | | /** |
1689 | | * Returns a thread name as "<aPoolName> #<n>" and increments the counter. |
1690 | | */ |
1691 | | nsCString GetNextThreadName(const nsACString& aPoolName); |
1692 | | |
1693 | | template<size_t LEN> |
1694 | | nsCString GetNextThreadName(const char (&aPoolName)[LEN]) |
1695 | | { |
1696 | | return GetNextThreadName(nsDependentCString(aPoolName, LEN - 1)); |
1697 | | } |
1698 | | |
1699 | | private: |
1700 | | mozilla::Atomic<uint32_t> mCounter; |
1701 | | |
1702 | | nsThreadPoolNaming(const nsThreadPoolNaming&) = delete; |
1703 | | void operator=(const nsThreadPoolNaming&) = delete; |
1704 | | }; |
1705 | | |
1706 | | /** |
1707 | | * Thread priority in most operating systems affect scheduling, not IO. This |
1708 | | * helper is used to set the current thread to low IO priority for the lifetime |
1709 | | * of the created object. You can only use this low priority IO setting within |
1710 | | * the context of the current thread. |
1711 | | */ |
1712 | | class MOZ_STACK_CLASS nsAutoLowPriorityIO |
1713 | | { |
1714 | | public: |
1715 | | nsAutoLowPriorityIO(); |
1716 | | ~nsAutoLowPriorityIO(); |
1717 | | |
1718 | | private: |
1719 | | bool lowIOPrioritySet; |
1720 | | #if defined(XP_MACOSX) |
1721 | | int oldPriority; |
1722 | | #endif |
1723 | | }; |
1724 | | |
1725 | | void |
1726 | | NS_SetMainThread(); |
1727 | | |
1728 | | // Used only on cooperatively scheduled "main" threads. Causes the thread to be |
1729 | | // considered a main thread and also causes GetCurrentVirtualThread to return |
1730 | | // aVirtualThread. |
1731 | | void |
1732 | | NS_SetMainThread(PRThread* aVirtualThread); |
1733 | | |
1734 | | // Used only on cooperatively scheduled "main" threads. Causes the thread to no |
1735 | | // longer be considered a main thread. Also causes GetCurrentVirtualThread() to |
1736 | | // return a unique value. |
1737 | | void |
1738 | | NS_UnsetMainThread(); |
1739 | | |
1740 | | /** |
1741 | | * Return the expiration time of the next timer to run on the current |
1742 | | * thread. If that expiration time is greater than aDefault, then |
1743 | | * return aDefault. aSearchBound specifies a maximum number of timers |
1744 | | * to examine to find a timer on the current thread. If no timer that |
1745 | | * will run on the current thread is found after examining |
1746 | | * aSearchBound timers, return the highest seen expiration time as a |
1747 | | * best effort guess. |
1748 | | * |
1749 | | * Timers with either the type nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY or |
1750 | | * nsITIMER::TYPE_REPEATING_SLACK_LOW_PRIORITY will be skipped when |
1751 | | * searching for the next expiration time. This enables timers to |
1752 | | * have lower priority than callbacks dispatched from |
1753 | | * nsIThread::IdleDispatch. |
1754 | | */ |
1755 | | extern mozilla::TimeStamp |
1756 | | NS_GetTimerDeadlineHintOnCurrentThread(mozilla::TimeStamp aDefault, uint32_t aSearchBound); |
1757 | | |
1758 | | namespace mozilla { |
1759 | | |
1760 | | /** |
1761 | | * Cooperative thread scheduling is governed by two rules: |
1762 | | * - Only one thread in the pool of cooperatively scheduled threads runs at a |
1763 | | * time. |
1764 | | * - Thread switching happens at well-understood safe points. |
1765 | | * |
1766 | | * In some cases we may want to treat all the threads in a cooperative pool as a |
1767 | | * single thread, while other parts of the code may want to view them as separate |
1768 | | * threads. GetCurrentVirtualThread() will return the same value for all |
1769 | | * threads in a cooperative thread pool. GetCurrentPhysicalThread will return a |
1770 | | * different value for each thread in the pool. |
1771 | | * |
1772 | | * Thread safety assertions are a concrete example where GetCurrentVirtualThread |
1773 | | * should be used. An object may want to assert that it only can be used on the |
1774 | | * thread that created it. Such assertions would normally prevent the object |
1775 | | * from being used on different cooperative threads. However, the object might |
1776 | | * really only care that it's used atomically. Cooperative scheduling guarantees |
1777 | | * that it will be (assuming we don't yield in the middle of modifying the |
1778 | | * object). So we can weaken the assertion to compare the virtual thread the |
1779 | | * object was created on to the virtual thread on which it's being used. This |
1780 | | * assertion allows the object to be used across threads in a cooperative thread |
1781 | | * pool while preventing accesses across preemptively scheduled threads (which |
1782 | | * would be unsafe). |
1783 | | */ |
1784 | | |
1785 | | // Returns the PRThread on which this code is running. |
1786 | | PRThread* |
1787 | | GetCurrentPhysicalThread(); |
1788 | | |
1789 | | // Returns a "virtual" PRThread that should only be used for comparison with |
1790 | | // other calls to GetCurrentVirtualThread. Two threads in the same cooperative |
1791 | | // thread pool will return the same virtual thread. Threads that are not |
1792 | | // cooperatively scheduled will have their own unique virtual PRThread (which |
1793 | | // will be equal to their physical PRThread). |
1794 | | // |
1795 | | // The return value of GetCurrentVirtualThread() is guaranteed not to change |
1796 | | // throughout the lifetime of a thread. |
1797 | | // |
1798 | | // Note that the original main thread (the first one created in the process) is |
1799 | | // considered as part of the pool of cooperative threads, so the return value of |
1800 | | // GetCurrentVirtualThread() for this thread (throughout its lifetime, even |
1801 | | // during shutdown) is the same as the return value from any other thread in the |
1802 | | // cooperative pool. |
1803 | | PRThread* |
1804 | | GetCurrentVirtualThread(); |
1805 | | |
1806 | | // These functions return event targets that can be used to dispatch to the |
1807 | | // current or main thread. They can also be used to test if you're on those |
1808 | | // threads (via IsOnCurrentThread). These functions should be used in preference |
1809 | | // to the nsIThread-based NS_Get{Current,Main}Thread functions since they will |
1810 | | // return more useful answers in the case of threads sharing an event loop. |
1811 | | |
1812 | | nsIEventTarget* |
1813 | | GetCurrentThreadEventTarget(); |
1814 | | |
1815 | | nsIEventTarget* |
1816 | | GetMainThreadEventTarget(); |
1817 | | |
1818 | | // These variants of the above functions assert that the given thread has a |
1819 | | // serial event target (i.e., that it's not part of a thread pool) and returns |
1820 | | // that. |
1821 | | |
1822 | | nsISerialEventTarget* |
1823 | | GetCurrentThreadSerialEventTarget(); |
1824 | | |
1825 | | nsISerialEventTarget* |
1826 | | GetMainThreadSerialEventTarget(); |
1827 | | |
1828 | | } // namespace mozilla |
1829 | | |
1830 | | #endif // nsThreadUtils_h__ |