Bug 1885602 - Part 5: Implement navigating to the SUMO help topic from the menu heade...
[gecko.git] / dom / webscheduling / WebTaskScheduler.h
blob18767be8a9999ba5f723897ac21d0b2e80fc63c3
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
3 */
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 #ifndef mozilla_dom_WebTaskScheduler_h
9 #define mozilla_dom_WebTaskScheduler_h
11 #include "nsThreadUtils.h"
12 #include "nsPIDOMWindow.h"
13 #include "nsWrapperCache.h"
14 #include "nsClassHashtable.h"
16 #include "mozilla/Variant.h"
17 #include "mozilla/dom/Promise.h"
18 #include "mozilla/dom/AbortFollower.h"
19 #include "mozilla/dom/TimeoutHandler.h"
20 #include "mozilla/dom/WebTaskSchedulingBinding.h"
22 namespace mozilla::dom {
23 class WebTaskQueue;
24 class WebTask : public LinkedListElement<RefPtr<WebTask>>,
25 public AbortFollower,
26 public SupportsWeakPtr {
27 friend class WebTaskScheduler;
29 public:
30 MOZ_CAN_RUN_SCRIPT bool Run();
32 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
34 NS_DECL_CYCLE_COLLECTION_CLASS(WebTask)
35 WebTask(uint32_t aEnqueueOrder, SchedulerPostTaskCallback& aCallback,
36 Promise* aPromise)
37 : mEnqueueOrder(aEnqueueOrder),
38 mCallback(&aCallback),
39 mPromise(aPromise),
40 mHasScheduled(false),
41 mOwnerQueue(nullptr) {}
43 void RunAbortAlgorithm() override;
45 bool HasScheduled() const { return mHasScheduled; }
47 uint32_t EnqueueOrder() const { return mEnqueueOrder; }
49 void SetWebTaskQueue(WebTaskQueue* aWebTaskQueue) {
50 mOwnerQueue = aWebTaskQueue;
53 private:
54 void SetHasScheduled(bool aHasScheduled) { mHasScheduled = aHasScheduled; }
56 uint32_t mEnqueueOrder;
58 RefPtr<SchedulerPostTaskCallback> mCallback;
59 RefPtr<Promise> mPromise;
61 bool mHasScheduled;
63 // WebTaskQueue owns WebTask, so it's okay to use a raw pointer
64 WebTaskQueue* mOwnerQueue;
66 ~WebTask() = default;
69 class WebTaskQueue {
70 public:
71 WebTaskQueue(uint32_t aKey, WebTaskScheduler* aScheduler)
72 : mOwnerKey(AsVariant(aKey)), mScheduler(aScheduler) {}
73 WebTaskQueue(TaskSignal* aKey, WebTaskScheduler* aScheduler)
74 : mOwnerKey(AsVariant(aKey)), mScheduler(aScheduler) {}
76 TaskPriority Priority() const { return mPriority; }
77 void SetPriority(TaskPriority aNewPriority) { mPriority = aNewPriority; }
79 LinkedList<RefPtr<WebTask>>& Tasks() { return mTasks; }
81 void AddTask(WebTask* aTask) {
82 mTasks.insertBack(aTask);
83 aTask->SetWebTaskQueue(this);
86 void RemoveEntryFromTaskQueueMapIfNeeded();
87 // TODO: To optimize it, we could have the scheduled and unscheduled
88 // tasks stored separately.
89 WebTask* GetFirstScheduledTask() {
90 for (const auto& task : mTasks) {
91 if (task->HasScheduled()) {
92 return task;
95 return nullptr;
98 ~WebTaskQueue() {
99 mOwnerKey = AsVariant(Nothing());
100 for (const auto& task : mTasks) {
101 task->SetWebTaskQueue(nullptr);
103 mTasks.clear();
106 private:
107 TaskPriority mPriority = TaskPriority::User_visible;
108 LinkedList<RefPtr<WebTask>> mTasks;
110 // When mOwnerKey is TaskSignal*, it means as long as
111 // WebTaskQueue is alive, the corresponding TaskSignal
112 // is alive, so using a raw pointer is ok.
113 Variant<Nothing, uint32_t, TaskSignal*> mOwnerKey;
115 // WebTaskScheduler owns WebTaskQueue as a hashtable value, so using a raw
116 // pointer points to WebTaskScheduler is ok.
117 WebTaskScheduler* mScheduler;
120 class WebTaskSchedulerMainThread;
121 class WebTaskSchedulerWorker;
123 class WebTaskScheduler : public nsWrapperCache, public SupportsWeakPtr {
124 friend class DelayedWebTaskHandler;
126 public:
127 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebTaskScheduler)
128 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebTaskScheduler)
130 static already_AddRefed<WebTaskSchedulerMainThread> CreateForMainThread(
131 nsGlobalWindowInner* aWindow);
133 static already_AddRefed<WebTaskSchedulerWorker> CreateForWorker(
134 WorkerPrivate* aWorkerPrivate);
136 explicit WebTaskScheduler(nsIGlobalObject* aParent);
138 already_AddRefed<Promise> PostTask(SchedulerPostTaskCallback& aCallback,
139 const SchedulerPostTaskOptions& aOptions);
141 nsIGlobalObject* GetParentObject() const { return mParent; }
143 virtual JSObject* WrapObject(JSContext* cx,
144 JS::Handle<JSObject*> aGivenProto) override;
146 WebTask* GetNextTask() const;
148 virtual void Disconnect();
150 void RunTaskSignalPriorityChange(TaskSignal* aTaskSignal);
152 void DeleteEntryFromStaticQueueMap(uint32_t aKey);
153 void DeleteEntryFromDynamicQueueMap(TaskSignal* aKey);
155 protected:
156 virtual ~WebTaskScheduler() = default;
157 nsCOMPtr<nsIGlobalObject> mParent;
159 uint32_t mNextEnqueueOrder;
161 private:
162 already_AddRefed<WebTask> CreateTask(
163 WebTaskQueue& aQueue, const Optional<OwningNonNull<AbortSignal>>& aSignal,
164 SchedulerPostTaskCallback& aCallback, Promise* aPromise);
166 bool QueueTask(WebTask* aTask);
168 WebTaskQueue& SelectTaskQueue(
169 const Optional<OwningNonNull<AbortSignal>>& aSignal,
170 const Optional<TaskPriority>& aPriority);
172 virtual nsresult SetTimeoutForDelayedTask(WebTask* aTask,
173 uint64_t aDelay) = 0;
174 virtual bool DispatchEventLoopRunnable() = 0;
176 nsClassHashtable<nsUint32HashKey, WebTaskQueue> mStaticPriorityTaskQueues;
177 nsClassHashtable<nsRefPtrHashKey<TaskSignal>, WebTaskQueue>
178 mDynamicPriorityTaskQueues;
181 class DelayedWebTaskHandler final : public TimeoutHandler {
182 public:
183 DelayedWebTaskHandler(JSContext* aCx, WebTaskScheduler* aScheduler,
184 WebTask* aTask)
185 : TimeoutHandler(aCx), mScheduler(aScheduler), mWebTask(aTask) {}
187 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
188 NS_DECL_CYCLE_COLLECTION_CLASS(DelayedWebTaskHandler)
190 MOZ_CAN_RUN_SCRIPT bool Call(const char* /* unused */) override {
191 if (mScheduler && mWebTask) {
192 MOZ_ASSERT(!mWebTask->HasScheduled());
193 if (!mScheduler->QueueTask(mWebTask)) {
194 return false;
197 return true;
200 private:
201 ~DelayedWebTaskHandler() override = default;
202 WeakPtr<WebTaskScheduler> mScheduler;
203 // WebTask gets added to WebTaskQueue, and WebTaskQueue keeps its alive.
204 WeakPtr<WebTask> mWebTask;
206 } // namespace mozilla::dom
207 #endif