diff --git a/image/DecodePool.cpp b/image/DecodePool.cpp index 753e53727ce8..2781bcc5a314 100644 --- a/image/DecodePool.cpp +++ b/image/DecodePool.cpp @@ -137,9 +137,9 @@ bool DecodePool::IsShuttingDown() const { return mShuttingDown; } class DecodingTask final : public Task { public: explicit DecodingTask(RefPtr&& aTask) - : Task(false, aTask->Priority() == TaskPriority::eLow - ? EventQueuePriority::Normal - : EventQueuePriority::RenderBlocking), + : Task(Kind::OffMainThreadOnly, aTask->Priority() == TaskPriority::eLow + ? EventQueuePriority::Normal + : EventQueuePriority::RenderBlocking), mTask(aTask) {} bool Run() override { diff --git a/js/xpconnect/src/XPCJSContext.cpp b/js/xpconnect/src/XPCJSContext.cpp index 6104f2c865ee..2e48ae2b5d98 100644 --- a/js/xpconnect/src/XPCJSContext.cpp +++ b/js/xpconnect/src/XPCJSContext.cpp @@ -1184,7 +1184,8 @@ class HelperThreadTaskHandler : public Task { JS::RunHelperThreadTask(); return true; } - explicit HelperThreadTaskHandler() : Task(false, EventQueuePriority::Normal) { + explicit HelperThreadTaskHandler() + : Task(Kind::OffMainThreadOnly, EventQueuePriority::Normal) { // Bug 1703185: Currently all tasks are run at the same priority. } diff --git a/xpcom/threads/IdleTaskRunner.cpp b/xpcom/threads/IdleTaskRunner.cpp index 8b467c54d6c9..4c3188a25669 100644 --- a/xpcom/threads/IdleTaskRunner.cpp +++ b/xpcom/threads/IdleTaskRunner.cpp @@ -31,7 +31,7 @@ already_AddRefed IdleTaskRunner::Create( class IdleTaskRunnerTask : public Task { public: explicit IdleTaskRunnerTask(IdleTaskRunner* aRunner) - : Task(true, EventQueuePriority::Idle), + : Task(Kind::MainThreadOnly, EventQueuePriority::Idle), mRunner(aRunner), mRequestInterrupt(aRunner->mRequestInterrupt) { SetManager(TaskController::Get()->GetIdleTaskManager()); diff --git a/xpcom/threads/TaskController.cpp b/xpcom/threads/TaskController.cpp index edb8ef853ab3..dbeff7716a95 100644 --- a/xpcom/threads/TaskController.cpp +++ b/xpcom/threads/TaskController.cpp @@ -331,7 +331,8 @@ void TaskController::RunPoolThread() { task = nextTask; } - if (task->IsMainThreadOnly() || task->mInProgress) { + if (task->GetKind() == Task::Kind::MainThreadOnly || + task->mInProgress) { continue; } @@ -416,7 +417,7 @@ void TaskController::RunPoolThread() { void TaskController::AddTask(already_AddRefed&& aTask) { RefPtr task(aTask); - if (!task->IsMainThreadOnly()) { + if (task->GetKind() == Task::Kind::OffMainThreadOnly) { MutexAutoLock lock(mPoolInitializationMutex); if (!mThreadPoolInitialized) { InitializeThreadPool(); @@ -453,10 +454,13 @@ void TaskController::AddTask(already_AddRefed&& aTask) { std::pair, Task::PriorityCompare>::iterator, bool> insertion; - if (task->IsMainThreadOnly()) { - insertion = mMainThreadTasks.insert(std::move(task)); - } else { - insertion = mThreadableTasks.insert(std::move(task)); + switch (task->GetKind()) { + case Task::Kind::MainThreadOnly: + insertion = mMainThreadTasks.insert(std::move(task)); + break; + case Task::Kind::OffMainThreadOnly: + insertion = mThreadableTasks.insert(std::move(task)); + break; } (*insertion.first)->mIterator = insertion.first; MOZ_ASSERT(insertion.second); @@ -527,7 +531,7 @@ void TaskController::ProcessPendingMTTask(bool aMayWait) { void TaskController::ReprioritizeTask(Task* aTask, uint32_t aPriority) { MutexAutoLock lock(mGraphMutex); std::set, Task::PriorityCompare>* queue = &mMainThreadTasks; - if (!aTask->IsMainThreadOnly()) { + if (aTask->GetKind() == Task::Kind::OffMainThreadOnly) { queue = &mThreadableTasks; } @@ -548,8 +552,8 @@ void TaskController::ReprioritizeTask(Task* aTask, uint32_t aPriority) { class RunnableTask : public Task { public: RunnableTask(already_AddRefed&& aRunnable, int32_t aPriority, - bool aMainThread = true) - : Task(aMainThread, aPriority), mRunnable(aRunnable) {} + Kind aKind) + : Task(aKind, aPriority), mRunnable(aRunnable) {} virtual bool Run() override { mRunnable->Run(); @@ -587,7 +591,8 @@ class RunnableTask : public Task { void TaskController::DispatchRunnable(already_AddRefed&& aRunnable, uint32_t aPriority, TaskManager* aManager) { - RefPtr task = new RunnableTask(std::move(aRunnable), aPriority); + RefPtr task = new RunnableTask(std::move(aRunnable), aPriority, + Task::Kind::MainThreadOnly); task->SetManager(aManager); TaskController::Get()->AddTask(task.forget()); @@ -812,7 +817,8 @@ bool TaskController::DoExecuteNextTaskOnlyMainThreadInternal( task = GetFinalDependency(task); - if (!task->IsMainThreadOnly() || task->mInProgress || + if (task->GetKind() == Task::Kind::OffMainThreadOnly || + task->mInProgress || (task->mTaskManager && task->mTaskManager->mCurrentSuspended)) { continue; } @@ -958,7 +964,7 @@ void TaskController::MaybeInterruptTask(Task* aTask) { Task* firstDependency = aTask->mDependencies.begin()->get(); if (aTask->GetPriority() <= firstDependency->GetPriority() && !firstDependency->mCompleted && - aTask->IsMainThreadOnly() == firstDependency->IsMainThreadOnly()) { + aTask->GetKind() == firstDependency->GetKind()) { // This task has the same or a higher priority as one of its dependencies, // never any need to interrupt. return; @@ -972,7 +978,7 @@ void TaskController::MaybeInterruptTask(Task* aTask) { return; } - if (aTask->IsMainThreadOnly()) { + if (aTask->GetKind() == Task::Kind::MainThreadOnly) { mMayHaveMainThreadTask = true; EnsureMainThreadTasksScheduled(); @@ -983,7 +989,7 @@ void TaskController::MaybeInterruptTask(Task* aTask) { // We could go through the steps above here and interrupt an off main // thread task in case it has a lower priority. - if (!finalDependency->IsMainThreadOnly()) { + if (finalDependency->GetKind() == Task::Kind::OffMainThreadOnly) { return; } diff --git a/xpcom/threads/TaskController.h b/xpcom/threads/TaskController.h index 184080002a10..d32a7396ee29 100644 --- a/xpcom/threads/TaskController.h +++ b/xpcom/threads/TaskController.h @@ -111,16 +111,31 @@ class TaskManager { }; // A Task is the the base class for any unit of work that may be scheduled. +// // Subclasses may specify their priority and whether they should be bound to -// the Gecko Main thread. When not bound to the main thread tasks may be -// executed on any available thread (including the main thread), but they may -// also be executed in parallel to any other task they do not have a dependency -// relationship with. Tasks will be run in order of object creation. +// either the Gecko Main thread or off main thread. When not bound to the main +// thread tasks may be executed on any available thread excluding the main +// thread, but they may also be executed in parallel to any other task they do +// not have a dependency relationship with. +// +// Tasks will be run in order of object creation. class Task { public: + enum class Kind : uint8_t { + // This task should be executed on any available thread excluding the Gecko + // Main thread. + OffMainThreadOnly, + + // This task should be executed on the Gecko Main thread. + MainThreadOnly + + // NOTE: "any available thread including the main thread" option is not + // supported (See bug 1839102). + }; + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Task) - bool IsMainThreadOnly() { return mMainThreadOnly; } + Kind GetKind() { return mKind; } // This returns the current task priority with its modifier applied. uint32_t GetPriority() { return mPriority + mPriorityModifier; } @@ -148,7 +163,7 @@ class Task { // This sets the TaskManager for the current task. Calling this after the // task has been added to the TaskController results in undefined behavior. void SetManager(TaskManager* aManager) { - MOZ_ASSERT(mMainThreadOnly); + MOZ_ASSERT(mKind == Kind::MainThreadOnly); MOZ_ASSERT(!mIsInGraph); mTaskManager = aManager; } @@ -178,15 +193,12 @@ class Task { #endif protected: - Task(bool aMainThreadOnly, + Task(Kind aKind, uint32_t aPriority = static_cast(kDefaultPriorityValue)) - : mMainThreadOnly(aMainThreadOnly), - mSeqNo(sCurrentTaskSeqNo++), - mPriority(aPriority) {} + : mKind(aKind), mSeqNo(sCurrentTaskSeqNo++), mPriority(aPriority) {} - Task(bool aMainThreadOnly, - EventQueuePriority aPriority = kDefaultPriorityValue) - : mMainThreadOnly(aMainThreadOnly), + Task(Kind aKind, EventQueuePriority aPriority = kDefaultPriorityValue) + : mKind(aKind), mSeqNo(sCurrentTaskSeqNo++), mPriority(static_cast(aPriority)) {} @@ -220,7 +232,7 @@ class Task { RefPtr mTaskManager; // Access to these variables is protected by the GraphMutex. - bool mMainThreadOnly; + Kind mKind; bool mCompleted = false; bool mInProgress = false; #ifdef DEBUG