Bug 1688832: part 5) Add `static` `AccessibleCaretManager::GetSelection`, `::GetFrame...
[gecko.git] / xpcom / threads / AbstractThread.h
blobef339986ddf9faca2af5f8eb19424d74b31434e8
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 #if !defined(AbstractThread_h_)
8 # define 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 // Returns an AbstractThread wrapper of a nsIThread.
55 static already_AddRefed<AbstractThread> CreateXPCOMThreadWrapper(
56 nsIThread* aThread, bool aRequireTailDispatch, bool aOnThread = false);
58 NS_DECL_THREADSAFE_ISUPPORTS
60 // We don't use NS_DECL_NSIEVENTTARGET so that we can remove the default
61 // |flags| parameter from Dispatch. Otherwise, a single-argument Dispatch call
62 // would be ambiguous.
63 NS_IMETHOD_(bool) IsOnCurrentThreadInfallible(void) override;
64 NS_IMETHOD IsOnCurrentThread(bool* _retval) override;
65 NS_IMETHOD Dispatch(already_AddRefed<nsIRunnable> event,
66 uint32_t flags) override;
67 NS_IMETHOD DispatchFromScript(nsIRunnable* event, uint32_t flags) override;
68 NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event,
69 uint32_t delay) override;
71 enum DispatchReason { NormalDispatch, TailDispatch };
72 virtual nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
73 DispatchReason aReason = NormalDispatch) = 0;
75 virtual bool IsCurrentThreadIn() const = 0;
77 // Returns a TaskDispatcher that will dispatch its tasks when the currently-
78 // running tasks pops off the stack.
80 // May only be called when running within the it is invoked up, and only on
81 // threads which support it.
82 virtual TaskDispatcher& TailDispatcher() = 0;
84 // Returns true if we have tail tasks scheduled, or if this isn't known.
85 // Returns false if we definitely don't have any tail tasks.
86 virtual bool MightHaveTailTasks() { return true; }
88 // Returns true if the tail dispatcher is available. In certain edge cases
89 // like shutdown, it might not be.
90 virtual bool IsTailDispatcherAvailable() { return true; }
92 // Helper functions for methods on the tail TasklDispatcher. These check
93 // HasTailTasks to avoid allocating a TailDispatcher if it isn't
94 // needed.
95 nsresult TailDispatchTasksFor(AbstractThread* aThread);
96 bool HasTailTasksFor(AbstractThread* aThread);
98 // Returns true if this supports the tail dispatcher.
99 bool SupportsTailDispatch() const { return mSupportsTailDispatch; }
101 // Returns true if this thread requires all dispatches originating from
102 // aThread go through the tail dispatcher.
103 bool RequiresTailDispatch(AbstractThread* aThread) const;
104 bool RequiresTailDispatchFromCurrentThread() const;
106 virtual nsIEventTarget* AsEventTarget() { MOZ_CRASH("Not an event target!"); }
108 // Returns the non-DocGroup version of AbstractThread on the main thread.
109 // A DocGroup-versioned one is available in
110 // DispatcherTrait::AbstractThreadFor(). Note:
111 // DispatcherTrait::AbstractThreadFor() SHALL be used when possible.
112 static AbstractThread* MainThread();
114 // Must be called exactly once during startup.
115 static void InitTLS();
116 static void InitMainThread();
117 static void ShutdownMainThread();
119 void DispatchStateChange(already_AddRefed<nsIRunnable> aRunnable);
121 static void DispatchDirectTask(already_AddRefed<nsIRunnable> aRunnable);
123 protected:
124 virtual ~AbstractThread() = default;
125 static MOZ_THREAD_LOCAL(AbstractThread*) sCurrentThreadTLS;
127 // True if we want to require that every task dispatched from tasks running in
128 // this queue go through our queue's tail dispatcher.
129 const bool mSupportsTailDispatch;
132 } // namespace mozilla
134 #endif