WebTaskSchedulerWorker.cpp (4046B)
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 #include "WebTaskSchedulerWorker.h" 8 9 #include "mozilla/dom/TimeoutManager.h" 10 #include "mozilla/dom/WorkerScope.h" 11 12 namespace mozilla::dom { 13 WebTaskWorkerRunnable::WebTaskWorkerRunnable( 14 WebTaskSchedulerWorker* aSchedulerWorker) 15 : WorkerSameThreadRunnable("WebTaskWorkerRunnable"), 16 mSchedulerWorker(aSchedulerWorker) { 17 MOZ_ASSERT(mSchedulerWorker); 18 } 19 20 RefPtr<WebTaskSchedulerWorker> WebTaskSchedulerWorker::Create( 21 WorkerPrivate* aWorkerPrivate) { 22 MOZ_ASSERT(aWorkerPrivate); 23 aWorkerPrivate->AssertIsOnWorkerThread(); 24 25 RefPtr<WebTaskSchedulerWorker> scheduler = 26 MakeRefPtr<WebTaskSchedulerWorker>(aWorkerPrivate); 27 28 scheduler->mWorkerRef = StrongWorkerRef::Create( 29 aWorkerPrivate, "WebTaskSchedulerWorker", [scheduler]() { 30 // Set mWorkerIsShuttingDown as true here to avoid dispatching tasks 31 // to worker thread. 32 scheduler->mWorkerIsShuttingDown = true; 33 }); 34 if (!scheduler->mWorkerRef) { 35 NS_WARNING("Create WebTaskScheduler when Worker is shutting down"); 36 scheduler->mWorkerIsShuttingDown = true; 37 } 38 return scheduler; 39 } 40 41 WebTaskSchedulerWorker::WebTaskSchedulerWorker(WorkerPrivate* aWorkerPrivate) 42 : WebTaskScheduler(aWorkerPrivate->GlobalScope()) {} 43 44 bool WebTaskWorkerRunnable::WorkerRun(JSContext* aCx, 45 WorkerPrivate* aWorkerPrivate) { 46 aWorkerPrivate->AssertIsOnWorkerThread(); 47 48 if (mSchedulerWorker) { 49 RefPtr<WebTask> task = 50 mSchedulerWorker->GetNextTask(false /* aIsMainThread */); 51 if (task) { 52 task->Run(); 53 } 54 } 55 return true; 56 } 57 58 nsresult WebTaskSchedulerWorker::SetTimeoutForDelayedTask( 59 WebTask* aTask, uint64_t aDelay, EventQueuePriority aPriority) { 60 if (mWorkerIsShuttingDown) { 61 return NS_ERROR_ABORT; 62 } 63 if (!mWorkerRef) { 64 return NS_ERROR_UNEXPECTED; 65 } 66 67 WorkerPrivate* workerPrivate = mWorkerRef->Private(); 68 MOZ_ASSERT(workerPrivate); 69 workerPrivate->AssertIsOnWorkerThread(); 70 71 JSContext* cx = nsContentUtils::GetCurrentJSContext(); 72 if (!cx) { 73 return NS_ERROR_UNEXPECTED; 74 } 75 RefPtr<DelayedWebTaskHandler> handler = 76 new DelayedWebTaskHandler(cx, this, aTask, aPriority); 77 ErrorResult rv; 78 79 int32_t delay = aDelay > INT32_MAX ? INT32_MAX : (int32_t)aDelay; 80 workerPrivate->SetTimeout(cx, handler, delay, 81 /* aIsInterval */ false, 82 Timeout::Reason::eDelayedWebTaskTimeout, rv); 83 return rv.StealNSResult(); 84 } 85 86 bool WebTaskSchedulerWorker::DispatchEventLoopRunnable( 87 EventQueuePriority aPriority) { 88 // aPriority is unused at the moment, we can't control 89 // the priorities for runnables on workers at the moment. 90 // 91 // This won't affect the correctness of this API because 92 // WebTaskScheduler maintains its own priority queues. 93 // 94 // It's just that we can't interfere the ordering between 95 // `WebTask` and other runnables. 96 if (mWorkerIsShuttingDown) { 97 return false; 98 } 99 100 if (!mWorkerRef) { 101 return false; 102 } 103 MOZ_ASSERT(mWorkerRef->Private()); 104 mWorkerRef->Private()->AssertIsOnWorkerThread(); 105 106 RefPtr<WebTaskWorkerRunnable> runnable = new WebTaskWorkerRunnable(this); 107 return runnable->Dispatch(mWorkerRef->Private()); 108 } 109 110 void WebTaskSchedulerWorker::Disconnect() { 111 if (mWorkerRef) { 112 mWorkerRef = nullptr; 113 } 114 WebTaskScheduler::Disconnect(); 115 } 116 117 void WebTaskSchedulerWorker:: 118 IncreaseNumNormalOrHighPriorityQueuesHaveTaskScheduled() { 119 ++mNumHighPriorityQueuesHaveTaskScheduled; 120 } 121 122 void WebTaskSchedulerWorker:: 123 DecreaseNumNormalOrHighPriorityQueuesHaveTaskScheduled() { 124 MOZ_ASSERT(mNumHighPriorityQueuesHaveTaskScheduled > 0); 125 --mNumHighPriorityQueuesHaveTaskScheduled; 126 } 127 128 } // namespace mozilla::dom