Bug 1932613 - temporarily disable browser_ml_end_to_end.js for permanent failures...
[gecko.git] / xpcom / threads / AbstractThread.h
blobbbc17cc5b011173fd565ef7cd9755ace5177dad4
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/. */
7 #ifndef XPCOM_THREADS_ABSTRACTTHREAD_H_
8 #define XPCOM_THREADS_ABSTRACTTHREAD_H_
10 #include "mozilla/AlreadyAddRefed.h"
11 #include "mozilla/ThreadLocal.h"
12 #include "nscore.h"
13 #include "nsISerialEventTarget.h"
14 #include "nsISupports.h"
16 class nsIEventTarget;
17 class nsIRunnable;
18 class nsIThread;
20 namespace mozilla {
22 class TaskDispatcher;
25 * We often want to run tasks on a target that guarantees that events will never
26 * run in parallel. There are various target types that achieve this - namely
27 * nsIThread and TaskQueue. Note that nsIThreadPool (which implements
28 * nsIEventTarget) does not have this property, so we do not want to use
29 * nsIEventTarget for this purpose. This class encapsulates the specifics of
30 * the structures we might use here and provides a consistent interface.
32 * At present, the supported AbstractThread implementations are TaskQueue,
33 * AbstractThread::MainThread() and XPCOMThreadWrapper which can wrap any
34 * nsThread.
36 * The primary use of XPCOMThreadWrapper is to allow any threads to provide
37 * Direct Task dispatching which is similar (but not identical to) the microtask
38 * semantics of JS promises. Instantiating a XPCOMThreadWrapper on the current
39 * nsThread is sufficient to enable direct task dispatching.
41 * You shouldn't use pointers when comparing AbstractThread or nsIThread to
42 * determine if you are currently on the thread, but instead use the
43 * nsISerialEventTarget::IsOnCurrentThread() method.
45 class AbstractThread : public nsISerialEventTarget {
46 public:
47 // Returns the AbstractThread that the caller is currently running in, or null
48 // if the caller is not running in an AbstractThread.
49 static AbstractThread* GetCurrent() { return sCurrentThreadTLS.get(); }
51 AbstractThread(bool aSupportsTailDispatch)
52 : mSupportsTailDispatch(aSupportsTailDispatch) {}
54 // We don't use NS_DECL_NSIEVENTTARGET so that we can remove the default
55 // |flags| parameter from Dispatch. Otherwise, a single-argument Dispatch call
56 // would be ambiguous.
57 using nsISerialEventTarget::IsOnCurrentThread;
58 NS_IMETHOD_(bool) IsOnCurrentThreadInfallible(void) override;
59 NS_IMETHOD IsOnCurrentThread(bool* _retval) override;
60 NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable> event,
61 uint32_t flags) override;
62 NS_IMETHOD DispatchFromScript(nsIRunnable* event, uint32_t flags) override;
63 NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event,
64 uint32_t delay) override;
66 enum DispatchReason { NormalDispatch, TailDispatch };
67 virtual nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
68 DispatchReason aReason = NormalDispatch) = 0;
70 virtual bool IsCurrentThreadIn() const = 0;
72 // Returns a TaskDispatcher that will dispatch its tasks when the currently-
73 // running tasks pops off the stack.
75 // May only be called when running within the it is invoked up, and only on
76 // threads which support it.
77 virtual TaskDispatcher& TailDispatcher() = 0;
79 // Returns true if we have tail tasks scheduled, or if this isn't known.
80 // Returns false if we definitely don't have any tail tasks.
81 virtual bool MightHaveTailTasks() { return true; }
83 // Returns true if the tail dispatcher is available. In certain edge cases
84 // like shutdown, it might not be.
85 virtual bool IsTailDispatcherAvailable() { return true; }
87 // Helper functions for methods on the tail TasklDispatcher. These check
88 // HasTailTasks to avoid allocating a TailDispatcher if it isn't
89 // needed.
90 nsresult TailDispatchTasksFor(AbstractThread* aThread);
91 bool HasTailTasksFor(AbstractThread* aThread);
93 // Returns true if this supports the tail dispatcher.
94 bool SupportsTailDispatch() const { return mSupportsTailDispatch; }
96 // Returns true if this thread requires all dispatches originating from
97 // aThread go through the tail dispatcher.
98 bool RequiresTailDispatch(AbstractThread* aThread) const;
99 bool RequiresTailDispatchFromCurrentThread() const;
101 virtual nsIEventTarget* AsEventTarget() { MOZ_CRASH("Not an event target!"); }
103 // Returns the non-DocGroup version of AbstractThread on the main thread.
104 // A DocGroup-versioned one is available in
105 // DispatcherTrait::AbstractThreadFor(). Note:
106 // DispatcherTrait::AbstractThreadFor() SHALL be used when possible.
107 static AbstractThread* MainThread();
109 // Must be called exactly once during startup.
110 static void InitTLS();
111 static void InitMainThread();
112 static void ShutdownMainThread();
114 void DispatchStateChange(already_AddRefed<nsIRunnable> aRunnable);
116 static void DispatchDirectTask(already_AddRefed<nsIRunnable> aRunnable);
118 protected:
119 virtual ~AbstractThread() = default;
120 static MOZ_THREAD_LOCAL(AbstractThread*) sCurrentThreadTLS;
122 // True if we want to require that every task dispatched from tasks running in
123 // this queue go through our queue's tail dispatcher.
124 const bool mSupportsTailDispatch;
127 } // namespace mozilla
129 #endif