Coverage Report

Created: 2018-09-25 14:53

/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__