Bug 1602167 - Make TaskQueue capable of retaining its dispatch flags r=froydnj

Makes TaskQueue's queue hold a struct with each runnable and its flags. When specified, flags will be stored and passed with NS_DISPATCH_AT_END when TaskQueue::Runner dispatches itself back to its event target.

Differential Revision: https://phabricator.services.mozilla.com/D56802

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Kristen Wright 2019-12-11 22:26:06 +00:00
parent 4abc5101ed
commit 89819fb253
2 changed files with 34 additions and 12 deletions

View File

@ -58,17 +58,19 @@ NS_IMPL_ISUPPORTS(TaskQueue::EventTargetWrapper, nsIEventTarget,
nsISerialEventTarget)
TaskQueue::TaskQueue(already_AddRefed<nsIEventTarget> aTarget,
const char* aName, bool aRequireTailDispatch)
const char* aName, bool aRequireTailDispatch,
bool aRetainFlags)
: AbstractThread(aRequireTailDispatch),
mTarget(aTarget),
mQueueMonitor("TaskQueue::Queue"),
mTailDispatcher(nullptr),
mShouldRetainFlags(aRetainFlags),
mIsRunning(false),
mIsShutdown(false),
mName(aName) {}
TaskQueue::TaskQueue(already_AddRefed<nsIEventTarget> aTarget,
bool aSupportsTailDispatch)
bool aSupportsTailDispatch, bool aRetainFlags)
: TaskQueue(std::move(aTarget), "Unnamed", aSupportsTailDispatch) {}
TaskQueue::~TaskQueue() {
@ -99,7 +101,11 @@ nsresult TaskQueue::DispatchLocked(nsCOMPtr<nsIRunnable>& aRunnable,
return currentThread->TailDispatcher().AddTask(this, aRunnable.forget());
}
mTasks.push(aRunnable.forget());
// If the task queue cares about individual flags, retain them in the struct.
uint32_t retainFlags = mShouldRetainFlags ? aFlags : 0;
mTasks.push({aRunnable.forget(), retainFlags});
if (mIsRunning) {
return NS_OK;
}
@ -176,7 +182,7 @@ already_AddRefed<nsISerialEventTarget> TaskQueue::WrapAsEventTarget() {
}
nsresult TaskQueue::Runner::Run() {
RefPtr<nsIRunnable> event;
TaskStruct event;
{
MonitorAutoLock mon(mQueue->mQueueMonitor);
MOZ_ASSERT(mQueue->mIsRunning);
@ -186,10 +192,10 @@ nsresult TaskQueue::Runner::Run() {
mon.NotifyAll();
return NS_OK;
}
event = mQueue->mTasks.front().forget();
event = std::move(mQueue->mTasks.front());
mQueue->mTasks.pop();
}
MOZ_ASSERT(event);
MOZ_ASSERT(event.event);
// Note that dropping the queue monitor before running the task, and
// taking the monitor again after the task has run ensures we have memory
@ -198,7 +204,7 @@ nsresult TaskQueue::Runner::Run() {
// in this task queue.
{
AutoTaskGuard g(mQueue);
event->Run();
event.event->Run();
}
// Drop the reference to event. The event will hold a reference to the
@ -206,7 +212,7 @@ nsresult TaskQueue::Runner::Run() {
// making assumptions what holds references to it. This is especially
// the case if the object is waiting for us to shutdown, so that it
// can shutdown (like in the MediaDecoderStateMachine's SHUTDOWN case).
event = nullptr;
event.event = nullptr;
{
MonitorAutoLock mon(mQueue->mQueueMonitor);
@ -224,7 +230,12 @@ nsresult TaskQueue::Runner::Run() {
// run in a loop here so that we don't hog the target. This means we may
// run on another thread next time, but we rely on the memory fences from
// mQueueMonitor for thread safety of non-threadsafe tasks.
nsresult rv = mQueue->mTarget->Dispatch(this, NS_DISPATCH_AT_END);
nsresult rv;
{
MonitorAutoLock mon(mQueue->mQueueMonitor);
rv = mQueue->mTarget->Dispatch(
this, mQueue->mTasks.front().flags | NS_DISPATCH_AT_END);
}
if (NS_FAILED(rv)) {
// Failed to dispatch, shutdown!
MonitorAutoLock mon(mQueue->mQueueMonitor);

View File

@ -54,10 +54,11 @@ class TaskQueue : public AbstractThread {
public:
explicit TaskQueue(already_AddRefed<nsIEventTarget> aTarget,
bool aSupportsTailDispatch = false);
bool aSupportsTailDispatch = false,
bool aRetainFlags = false);
TaskQueue(already_AddRefed<nsIEventTarget> aTarget, const char* aName,
bool aSupportsTailDispatch = false);
bool aSupportsTailDispatch = false, bool aRetainFlags = false);
TaskDispatcher& TailDispatcher() override;
@ -127,8 +128,13 @@ class TaskQueue : public AbstractThread {
// Monitor that protects the queue and mIsRunning;
Monitor mQueueMonitor;
typedef struct {
nsCOMPtr<nsIRunnable> event;
uint32_t flags;
} TaskStruct;
// Queue of tasks to run.
std::queue<nsCOMPtr<nsIRunnable>> mTasks;
std::queue<TaskStruct> mTasks;
// The thread currently running the task queue. We store a reference
// to this so that IsCurrentThreadIn() can tell if the current thread
@ -176,6 +182,11 @@ class TaskQueue : public AbstractThread {
TaskDispatcher* mTailDispatcher;
// TaskQueues should specify if they want all tasks to dispatch with their
// original flags included, which means the flags will be retained in the
// TaskStruct.
bool mShouldRetainFlags;
// True if we've dispatched an event to the target to execute events from
// the queue.
bool mIsRunning;