Bug 130118 P2 Make TaskQueue implement nsIEventTarget. r=bholley

This commit is contained in:
Ben Kelly 2016-09-12 11:21:01 -07:00
Родитель 157b0fe1ed
Коммит 64919e3546
2 изменённых файлов: 83 добавлений и 1 удалений

Просмотреть файл

@ -6,10 +6,62 @@
#include "mozilla/TaskQueue.h"
#include "nsIEventTarget.h"
#include "nsThreadUtils.h"
namespace mozilla {
class TaskQueue::EventTargetWrapper final : public nsIEventTarget
{
RefPtr<TaskQueue> mTaskQueue;
~EventTargetWrapper()
{
}
public:
explicit EventTargetWrapper(TaskQueue* aTaskQueue)
: mTaskQueue(aTaskQueue)
{
MOZ_ASSERT(mTaskQueue);
}
NS_IMETHOD
DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags) override
{
nsCOMPtr<nsIRunnable> ref = aEvent;
return Dispatch(ref.forget(), aFlags);
}
NS_IMETHOD
Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags) override
{
nsCOMPtr<nsIRunnable> runnable = aEvent;
MonitorAutoLock mon(mTaskQueue->mQueueMonitor);
return mTaskQueue->DispatchLocked(/* passed by ref */runnable,
AbortIfFlushing,
DontAssertDispatchSuccess,
NormalDispatch);
}
NS_IMETHOD
DelayedDispatch(already_AddRefed<nsIRunnable>, uint32_t aFlags) override
{
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHOD
IsOnCurrentThread(bool* aResult) override
{
*aResult = mTaskQueue->IsCurrentThreadIn();
return NS_OK;
}
NS_DECL_THREADSAFE_ISUPPORTS
};
NS_IMPL_ISUPPORTS(TaskQueue::EventTargetWrapper, nsIEventTarget)
TaskQueue::TaskQueue(already_AddRefed<nsIEventTarget> aTarget,
bool aRequireTailDispatch)
: AbstractThread(aRequireTailDispatch)
@ -143,6 +195,13 @@ TaskQueue::IsCurrentThreadIn()
return in;
}
already_AddRefed<nsIEventTarget>
TaskQueue::WrapAsEventTarget()
{
nsCOMPtr<nsIEventTarget> ref = new EventTargetWrapper(this);
return ref.forget();
}
nsresult
TaskQueue::Runner::Run()
{

Просмотреть файл

@ -29,7 +29,26 @@ typedef MozPromise<bool, bool, false> ShutdownPromise;
// they're received, and are guaranteed to not be executed concurrently.
// They may be executed on different threads, and a memory barrier is used
// to make this threadsafe for objects that aren't already threadsafe.
class TaskQueue : public AbstractThread {
//
// Note, since a TaskQueue can also be converted to an nsIEventTarget using
// WrapAsEventTarget() its possible to construct a hierarchy of TaskQueues.
// Consider these three TaskQueues:
//
// TQ1 dispatches to the main thread
// TQ2 dispatches to TQ1
// TQ3 dispatches to TQ1
//
// This ensures there is only ever a single runnable from the entire chain on
// the main thread. It also ensures that TQ2 and TQ3 only have a single runnable
// in TQ1 at any time.
//
// This arrangement lets you prioritize work by dispatching runnables directly
// to TQ1. You can issue many runnables for important work. Meanwhile the TQ2
// and TQ3 work will always execute at most one runnable and then yield.
class TaskQueue : public AbstractThread
{
class EventTargetWrapper;
public:
explicit TaskQueue(already_AddRefed<nsIEventTarget> aTarget,
bool aSupportsTailDispatch = false);
@ -76,6 +95,10 @@ public:
// the task queue.
bool IsCurrentThreadIn() override;
// Create a new nsIEventTarget wrapper object that dispatches to this
// TaskQueue.
already_AddRefed<nsIEventTarget> WrapAsEventTarget();
protected:
virtual ~TaskQueue();