1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:expandtab:shiftwidth=2:tabstop=2:
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/dom/Promise.h"
17 #include "mozilla/dom/AbortFollower.h"
18 #include "mozilla/dom/TimeoutHandler.h"
19 #include "mozilla/dom/WebTaskSchedulingBinding.h"
21 namespace mozilla::dom
{
22 class WebTask
: public LinkedListElement
<RefPtr
<WebTask
>>,
24 public SupportsWeakPtr
{
25 friend class WebTaskScheduler
;
28 MOZ_CAN_RUN_SCRIPT
bool Run();
30 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
32 NS_DECL_CYCLE_COLLECTION_CLASS(WebTask
)
33 WebTask(uint32_t aEnqueueOrder
, SchedulerPostTaskCallback
& aCallback
,
35 : mEnqueueOrder(aEnqueueOrder
),
36 mCallback(&aCallback
),
38 mHasScheduled(false) {}
40 void RunAbortAlgorithm() override
;
42 bool HasScheduled() const { return mHasScheduled
; }
44 uint32_t EnqueueOrder() const { return mEnqueueOrder
; }
47 void SetHasScheduled(bool aHasScheduled
) { mHasScheduled
= aHasScheduled
; }
49 uint32_t mEnqueueOrder
;
51 RefPtr
<SchedulerPostTaskCallback
> mCallback
;
52 RefPtr
<Promise
> mPromise
;
61 WebTaskQueue() = default;
63 TaskPriority
Priority() const { return mPriority
; }
64 void SetPriority(TaskPriority aNewPriority
) { mPriority
= aNewPriority
; }
66 LinkedList
<RefPtr
<WebTask
>>& Tasks() { return mTasks
; }
68 void AddTask(WebTask
* aTask
) { mTasks
.insertBack(aTask
); }
70 // TODO: To optimize it, we could have the scheduled and unscheduled
71 // tasks stored separately.
72 WebTask
* GetFirstScheduledTask() {
73 for (const auto& task
: mTasks
) {
74 if (task
->HasScheduled()) {
81 ~WebTaskQueue() { mTasks
.clear(); }
84 TaskPriority mPriority
= TaskPriority::User_visible
;
85 LinkedList
<RefPtr
<WebTask
>> mTasks
;
88 class WebTaskSchedulerMainThread
;
89 class WebTaskSchedulerWorker
;
91 class WebTaskScheduler
: public nsWrapperCache
, public SupportsWeakPtr
{
92 friend class DelayedWebTaskHandler
;
95 NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(WebTaskScheduler
)
96 NS_DECL_CYCLE_COLLECTION_NATIVE_WRAPPERCACHE_CLASS(WebTaskScheduler
)
98 static already_AddRefed
<WebTaskSchedulerMainThread
> CreateForMainThread(
99 nsGlobalWindowInner
* aWindow
);
101 static already_AddRefed
<WebTaskSchedulerWorker
> CreateForWorker(
102 WorkerPrivate
* aWorkerPrivate
);
104 explicit WebTaskScheduler(nsIGlobalObject
* aParent
);
106 already_AddRefed
<Promise
> PostTask(SchedulerPostTaskCallback
& aCallback
,
107 const SchedulerPostTaskOptions
& aOptions
);
109 nsIGlobalObject
* GetParentObject() const { return mParent
; }
111 virtual JSObject
* WrapObject(JSContext
* cx
,
112 JS::Handle
<JSObject
*> aGivenProto
) override
;
114 WebTask
* GetNextTask() const;
118 void RunTaskSignalPriorityChange(TaskSignal
* aTaskSignal
);
121 virtual ~WebTaskScheduler() = default;
122 nsCOMPtr
<nsIGlobalObject
> mParent
;
124 uint32_t mNextEnqueueOrder
;
127 already_AddRefed
<WebTask
> CreateTask(
128 WebTaskQueue
& aQueue
, const Optional
<OwningNonNull
<AbortSignal
>>& aSignal
,
129 SchedulerPostTaskCallback
& aCallback
, Promise
* aPromise
);
131 bool QueueTask(WebTask
* aTask
);
133 WebTaskQueue
& SelectTaskQueue(
134 const Optional
<OwningNonNull
<AbortSignal
>>& aSignal
,
135 const Optional
<TaskPriority
>& aPriority
);
137 virtual nsresult
SetTimeoutForDelayedTask(WebTask
* aTask
,
138 uint64_t aDelay
) = 0;
139 virtual bool DispatchEventLoopRunnable() = 0;
141 nsClassHashtable
<nsUint32HashKey
, WebTaskQueue
> mStaticPriorityTaskQueues
;
142 nsClassHashtable
<nsPtrHashKey
<TaskSignal
>, WebTaskQueue
>
143 mDynamicPriorityTaskQueues
;
146 class DelayedWebTaskHandler final
: public TimeoutHandler
{
148 DelayedWebTaskHandler(JSContext
* aCx
, WebTaskScheduler
* aScheduler
,
150 : TimeoutHandler(aCx
), mScheduler(aScheduler
), mWebTask(aTask
) {}
152 NS_DECL_CYCLE_COLLECTING_ISUPPORTS
153 NS_DECL_CYCLE_COLLECTION_CLASS(DelayedWebTaskHandler
)
155 MOZ_CAN_RUN_SCRIPT
bool Call(const char* /* unused */) override
{
156 if (mScheduler
&& mWebTask
) {
157 MOZ_ASSERT(!mWebTask
->HasScheduled());
158 if (!mScheduler
->QueueTask(mWebTask
)) {
166 ~DelayedWebTaskHandler() override
= default;
167 WeakPtr
<WebTaskScheduler
> mScheduler
;
168 // WebTask gets added to WebTaskQueue, and WebTaskQueue keeps its alive.
169 WeakPtr
<WebTask
> mWebTask
;
171 } // namespace mozilla::dom