mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-04-01 12:03:08 +00:00
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:
parent
4abc5101ed
commit
89819fb253
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user