зеркало из https://github.com/mozilla/gecko-dev.git
Bug 130118 P2 Make TaskQueue implement nsIEventTarget. r=bholley
This commit is contained in:
Родитель
157b0fe1ed
Коммит
64919e3546
|
@ -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();
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче