зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1416724 - part 1 - AbstractThread::Dispatch should propage errors if failing the dispatching of Runnables, r=jwwang
This commit is contained in:
Родитель
a22e59eff8
Коммит
e521e16895
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "mozilla/TaskQueue.h"
|
#include "mozilla/TaskQueue.h"
|
||||||
#include "mozilla/MozPromise.h"
|
#include "mozilla/MozPromise.h"
|
||||||
|
#include "mozilla/Unused.h"
|
||||||
|
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "mozilla/SharedThreadPool.h"
|
#include "mozilla/SharedThreadPool.h"
|
||||||
|
@ -60,12 +61,11 @@ public:
|
||||||
|
|
||||||
if (--mIterations == 0) {
|
if (--mIterations == 0) {
|
||||||
mPromise->ResolveOrReject(mValue, __func__);
|
mPromise->ResolveOrReject(mValue, __func__);
|
||||||
} else {
|
return NS_OK;
|
||||||
nsCOMPtr<nsIRunnable> r = this;
|
|
||||||
mTaskQueue->Dispatch(r.forget());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return NS_OK;
|
nsCOMPtr<nsIRunnable> r = this;
|
||||||
|
return mTaskQueue->Dispatch(r.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Cancel() {
|
void Cancel() {
|
||||||
|
@ -87,7 +87,7 @@ void
|
||||||
RunOnTaskQueue(TaskQueue* aQueue, FunctionType aFun)
|
RunOnTaskQueue(TaskQueue* aQueue, FunctionType aFun)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("RunOnTaskQueue", aFun);
|
nsCOMPtr<nsIRunnable> r = NS_NewRunnableFunction("RunOnTaskQueue", aFun);
|
||||||
aQueue->Dispatch(r.forget());
|
Unused << aQueue->Dispatch(r.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
// std::function can't come soon enough. :-(
|
// std::function can't come soon enough. :-(
|
||||||
|
@ -162,11 +162,11 @@ TEST(MozPromise, AsyncResolve)
|
||||||
RefPtr<DelayedResolveOrReject> c = new DelayedResolveOrReject(queue, p, RRValue::MakeReject(32.0), 7);
|
RefPtr<DelayedResolveOrReject> c = new DelayedResolveOrReject(queue, p, RRValue::MakeReject(32.0), 7);
|
||||||
|
|
||||||
nsCOMPtr<nsIRunnable> ref = a.get();
|
nsCOMPtr<nsIRunnable> ref = a.get();
|
||||||
queue->Dispatch(ref.forget());
|
Unused << queue->Dispatch(ref.forget());
|
||||||
ref = b.get();
|
ref = b.get();
|
||||||
queue->Dispatch(ref.forget());
|
Unused << queue->Dispatch(ref.forget());
|
||||||
ref = c.get();
|
ref = c.get();
|
||||||
queue->Dispatch(ref.forget());
|
Unused << queue->Dispatch(ref.forget());
|
||||||
|
|
||||||
p->Then(queue, __func__, [queue, a, b, c] (int aResolveValue) -> void {
|
p->Then(queue, __func__, [queue, a, b, c] (int aResolveValue) -> void {
|
||||||
EXPECT_EQ(aResolveValue, 42);
|
EXPECT_EQ(aResolveValue, 42);
|
||||||
|
@ -197,7 +197,7 @@ TEST(MozPromise, CompletionPromises)
|
||||||
[queue] (int aVal) -> RefPtr<TestPromise> {
|
[queue] (int aVal) -> RefPtr<TestPromise> {
|
||||||
RefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
|
RefPtr<TestPromise::Private> p = new TestPromise::Private(__func__);
|
||||||
nsCOMPtr<nsIRunnable> resolver = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(aVal - 8), 10);
|
nsCOMPtr<nsIRunnable> resolver = new DelayedResolveOrReject(queue, p, RRValue::MakeResolve(aVal - 8), 10);
|
||||||
queue->Dispatch(resolver.forget());
|
Unused << queue->Dispatch(resolver.forget());
|
||||||
return RefPtr<TestPromise>(p);
|
return RefPtr<TestPromise>(p);
|
||||||
},
|
},
|
||||||
DO_FAIL)
|
DO_FAIL)
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "mozilla/SharedThreadPool.h"
|
#include "mozilla/SharedThreadPool.h"
|
||||||
#include "mozilla/StateWatching.h"
|
#include "mozilla/StateWatching.h"
|
||||||
#include "mozilla/TaskQueue.h"
|
#include "mozilla/TaskQueue.h"
|
||||||
|
#include "mozilla/Unused.h"
|
||||||
#include "nsISupportsImpl.h"
|
#include "nsISupportsImpl.h"
|
||||||
#include "VideoUtils.h"
|
#include "VideoUtils.h"
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ TEST(WatchManager, Shutdown)
|
||||||
WatchManager<Foo> manager(p, queue);
|
WatchManager<Foo> manager(p, queue);
|
||||||
Watchable<bool> notifier(false, "notifier");
|
Watchable<bool> notifier(false, "notifier");
|
||||||
|
|
||||||
queue->Dispatch(NS_NewRunnableFunction(
|
Unused << queue->Dispatch(NS_NewRunnableFunction(
|
||||||
"TestStateWatching::WatchManager_Shutdown_Test::TestBody", [&]() {
|
"TestStateWatching::WatchManager_Shutdown_Test::TestBody", [&]() {
|
||||||
manager.Watch(notifier, &Foo::Notify);
|
manager.Watch(notifier, &Foo::Notify);
|
||||||
notifier = true; // Trigger the call to Foo::Notify().
|
notifier = true; // Trigger the call to Foo::Notify().
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
#include "mozilla/SharedThreadPool.h"
|
#include "mozilla/SharedThreadPool.h"
|
||||||
#include "mozilla/TaskQueue.h"
|
#include "mozilla/TaskQueue.h"
|
||||||
|
#include "mozilla/Unused.h"
|
||||||
#include "VideoUtils.h"
|
#include "VideoUtils.h"
|
||||||
|
|
||||||
namespace TestTaskQueue {
|
namespace TestTaskQueue {
|
||||||
|
@ -29,15 +30,15 @@ TEST(TaskQueue, EventOrder)
|
||||||
|
|
||||||
// We expect task1 happens before task3.
|
// We expect task1 happens before task3.
|
||||||
for (int i = 0; i < 10000; ++i) {
|
for (int i = 0; i < 10000; ++i) {
|
||||||
tq1->Dispatch(
|
Unused << tq1->Dispatch(
|
||||||
NS_NewRunnableFunction(
|
NS_NewRunnableFunction(
|
||||||
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
||||||
[&]() {
|
[&]() {
|
||||||
tq2->Dispatch(NS_NewRunnableFunction(
|
Unused << tq2->Dispatch(NS_NewRunnableFunction(
|
||||||
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
||||||
[]() { // task0
|
[]() { // task0
|
||||||
}));
|
}));
|
||||||
tq3->Dispatch(NS_NewRunnableFunction(
|
Unused << tq3->Dispatch(NS_NewRunnableFunction(
|
||||||
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
||||||
[&]() { // task1
|
[&]() { // task1
|
||||||
EXPECT_EQ(1, ++counter);
|
EXPECT_EQ(1, ++counter);
|
||||||
|
@ -46,10 +47,10 @@ TEST(TaskQueue, EventOrder)
|
||||||
++sync;
|
++sync;
|
||||||
mon.Notify();
|
mon.Notify();
|
||||||
}));
|
}));
|
||||||
tq2->Dispatch(NS_NewRunnableFunction(
|
Unused << tq2->Dispatch(NS_NewRunnableFunction(
|
||||||
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
||||||
[&]() { // task2
|
[&]() { // task2
|
||||||
tq3->Dispatch(NS_NewRunnableFunction(
|
Unused << tq3->Dispatch(NS_NewRunnableFunction(
|
||||||
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
"TestTaskQueue::TaskQueue_EventOrder_Test::TestBody",
|
||||||
[&]() { // task3
|
[&]() { // task3
|
||||||
EXPECT_EQ(0, --counter);
|
EXPECT_EQ(0, --counter);
|
||||||
|
@ -60,7 +61,6 @@ TEST(TaskQueue, EventOrder)
|
||||||
}));
|
}));
|
||||||
}));
|
}));
|
||||||
}),
|
}),
|
||||||
AbstractThread::AssertDispatchSuccess,
|
|
||||||
AbstractThread::TailDispatch);
|
AbstractThread::TailDispatch);
|
||||||
|
|
||||||
// Ensure task1 and task3 are done before next loop.
|
// Ensure task1 and task3 are done before next loop.
|
||||||
|
|
|
@ -47,19 +47,15 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
virtual nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
||||||
DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
|
|
||||||
DispatchReason aReason = NormalDispatch) override
|
DispatchReason aReason = NormalDispatch) override
|
||||||
{
|
{
|
||||||
AbstractThread* currentThread;
|
AbstractThread* currentThread;
|
||||||
if (aReason != TailDispatch && (currentThread = GetCurrent()) && RequiresTailDispatch(currentThread)) {
|
if (aReason != TailDispatch && (currentThread = GetCurrent()) && RequiresTailDispatch(currentThread)) {
|
||||||
currentThread->TailDispatcher().AddTask(this, Move(aRunnable), aFailureHandling);
|
return currentThread->TailDispatcher().AddTask(this, Move(aRunnable));
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RefPtr<nsIRunnable> runner(new Runner(this, Move(aRunnable), false /* already drained by TaskGroupRunnable */));
|
RefPtr<nsIRunnable> runner(new Runner(this, Move(aRunnable), false /* already drained by TaskGroupRunnable */));
|
||||||
nsresult rv = mTarget->Dispatch(runner.forget(), NS_DISPATCH_NORMAL);
|
return mTarget->Dispatch(runner.forget(), NS_DISPATCH_NORMAL);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aFailureHandling == DontAssertDispatchSuccess || NS_SUCCEEDED(rv));
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prevent a GCC warning about the other overload of Dispatch being hidden.
|
// Prevent a GCC warning about the other overload of Dispatch being hidden.
|
||||||
|
@ -223,8 +219,7 @@ AbstractThread::DispatchFromScript(nsIRunnable* aEvent, uint32_t aFlags)
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
AbstractThread::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
|
AbstractThread::Dispatch(already_AddRefed<nsIRunnable> aEvent, uint32_t aFlags)
|
||||||
{
|
{
|
||||||
Dispatch(Move(aEvent), DontAssertDispatchSuccess, NormalDispatch);
|
return Dispatch(Move(aEvent), NormalDispatch);
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
|
@ -234,12 +229,14 @@ AbstractThread::DelayedDispatch(already_AddRefed<nsIRunnable> aEvent,
|
||||||
return NS_ERROR_NOT_IMPLEMENTED;
|
return NS_ERROR_NOT_IMPLEMENTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
nsresult
|
||||||
AbstractThread::TailDispatchTasksFor(AbstractThread* aThread)
|
AbstractThread::TailDispatchTasksFor(AbstractThread* aThread)
|
||||||
{
|
{
|
||||||
if (MightHaveTailTasks()) {
|
if (MightHaveTailTasks()) {
|
||||||
TailDispatcher().DispatchTasksFor(aThread);
|
return TailDispatcher().DispatchTasksFor(aThread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
|
|
|
@ -67,10 +67,8 @@ public:
|
||||||
NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override;
|
NS_IMETHOD DispatchFromScript(nsIRunnable *event, uint32_t flags) override;
|
||||||
NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay) override;
|
NS_IMETHOD DelayedDispatch(already_AddRefed<nsIRunnable> event, uint32_t delay) override;
|
||||||
|
|
||||||
enum DispatchFailureHandling { AssertDispatchSuccess, DontAssertDispatchSuccess };
|
|
||||||
enum DispatchReason { NormalDispatch, TailDispatch };
|
enum DispatchReason { NormalDispatch, TailDispatch };
|
||||||
virtual nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
virtual nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
||||||
DispatchFailureHandling aHandling = AssertDispatchSuccess,
|
|
||||||
DispatchReason aReason = NormalDispatch) = 0;
|
DispatchReason aReason = NormalDispatch) = 0;
|
||||||
|
|
||||||
virtual bool IsCurrentThreadIn() = 0;
|
virtual bool IsCurrentThreadIn() = 0;
|
||||||
|
@ -89,7 +87,7 @@ public:
|
||||||
// Helper functions for methods on the tail TasklDispatcher. These check
|
// Helper functions for methods on the tail TasklDispatcher. These check
|
||||||
// HasTailTasks to avoid allocating a TailDispatcher if it isn't
|
// HasTailTasks to avoid allocating a TailDispatcher if it isn't
|
||||||
// needed.
|
// needed.
|
||||||
void TailDispatchTasksFor(AbstractThread* aThread);
|
nsresult TailDispatchTasksFor(AbstractThread* aThread);
|
||||||
bool HasTailTasksFor(AbstractThread* aThread);
|
bool HasTailTasksFor(AbstractThread* aThread);
|
||||||
|
|
||||||
// Returns true if this supports the tail dispatcher.
|
// Returns true if this supports the tail dispatcher.
|
||||||
|
|
|
@ -155,8 +155,7 @@ private:
|
||||||
mMirrors[i]->OwnerThread()->Dispatch(
|
mMirrors[i]->OwnerThread()->Dispatch(
|
||||||
NewRunnableMethod("AbstractMirror::NotifyDisconnected",
|
NewRunnableMethod("AbstractMirror::NotifyDisconnected",
|
||||||
mMirrors[i],
|
mMirrors[i],
|
||||||
&AbstractMirror<T>::NotifyDisconnected),
|
&AbstractMirror<T>::NotifyDisconnected));
|
||||||
AbstractThread::DontAssertDispatchSuccess);
|
|
||||||
}
|
}
|
||||||
mMirrors.Clear();
|
mMirrors.Clear();
|
||||||
}
|
}
|
||||||
|
@ -338,7 +337,7 @@ private:
|
||||||
aCanonical,
|
aCanonical,
|
||||||
&AbstractCanonical<T>::AddMirror,
|
&AbstractCanonical<T>::AddMirror,
|
||||||
this);
|
this);
|
||||||
aCanonical->OwnerThread()->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess);
|
aCanonical->OwnerThread()->Dispatch(r.forget());
|
||||||
mCanonical = aCanonical;
|
mCanonical = aCanonical;
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
|
@ -357,7 +356,7 @@ private:
|
||||||
mCanonical,
|
mCanonical,
|
||||||
&AbstractCanonical<T>::RemoveMirror,
|
&AbstractCanonical<T>::RemoveMirror,
|
||||||
this);
|
this);
|
||||||
mCanonical->OwnerThread()->Dispatch(r.forget(), AbstractThread::DontAssertDispatchSuccess);
|
mCanonical->OwnerThread()->Dispatch(r.forget());
|
||||||
mCanonical = nullptr;
|
mCanonical = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,11 +54,10 @@ public:
|
||||||
|
|
||||||
// Regular tasks are dispatched asynchronously, and run after state change
|
// Regular tasks are dispatched asynchronously, and run after state change
|
||||||
// tasks.
|
// tasks.
|
||||||
virtual void AddTask(AbstractThread* aThread,
|
virtual nsresult AddTask(AbstractThread* aThread,
|
||||||
already_AddRefed<nsIRunnable> aRunnable,
|
already_AddRefed<nsIRunnable> aRunnable) = 0;
|
||||||
AbstractThread::DispatchFailureHandling aFailureHandling = AbstractThread::AssertDispatchSuccess) = 0;
|
|
||||||
|
|
||||||
virtual void DispatchTasksFor(AbstractThread* aThread) = 0;
|
virtual nsresult DispatchTasksFor(AbstractThread* aThread) = 0;
|
||||||
virtual bool HasTasksFor(AbstractThread* aThread) = 0;
|
virtual bool HasTasksFor(AbstractThread* aThread) = 0;
|
||||||
virtual void DrainDirectTasks() = 0;
|
virtual void DrainDirectTasks() = 0;
|
||||||
};
|
};
|
||||||
|
@ -122,9 +121,8 @@ public:
|
||||||
EnsureTaskGroup(aThread).mStateChangeTasks.AppendElement(r.forget());
|
EnsureTaskGroup(aThread).mStateChangeTasks.AppendElement(r.forget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddTask(AbstractThread* aThread,
|
nsresult AddTask(AbstractThread* aThread,
|
||||||
already_AddRefed<nsIRunnable> aRunnable,
|
already_AddRefed<nsIRunnable> aRunnable) override
|
||||||
AbstractThread::DispatchFailureHandling aFailureHandling) override
|
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIRunnable> r = aRunnable;
|
nsCOMPtr<nsIRunnable> r = aRunnable;
|
||||||
MOZ_RELEASE_ASSERT(r);
|
MOZ_RELEASE_ASSERT(r);
|
||||||
|
@ -139,11 +137,7 @@ public:
|
||||||
PerThreadTaskGroup& group = *mTaskGroups.LastElement();
|
PerThreadTaskGroup& group = *mTaskGroups.LastElement();
|
||||||
group.mRegularTasks.AppendElement(r.forget());
|
group.mRegularTasks.AppendElement(r.forget());
|
||||||
|
|
||||||
// The task group needs to assert dispatch success if any of the runnables
|
return NS_OK;
|
||||||
// it's dispatching want to assert it.
|
|
||||||
if (aFailureHandling == AbstractThread::AssertDispatchSuccess) {
|
|
||||||
group.mFailureHandling = AbstractThread::AssertDispatchSuccess;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HasTasksFor(AbstractThread* aThread) override
|
bool HasTasksFor(AbstractThread* aThread) override
|
||||||
|
@ -152,15 +146,27 @@ public:
|
||||||
(aThread == AbstractThread::GetCurrent() && HaveDirectTasks());
|
(aThread == AbstractThread::GetCurrent() && HaveDirectTasks());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DispatchTasksFor(AbstractThread* aThread) override
|
nsresult DispatchTasksFor(AbstractThread* aThread) override
|
||||||
{
|
{
|
||||||
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
// Dispatch all groups that match |aThread|.
|
// Dispatch all groups that match |aThread|.
|
||||||
for (size_t i = 0; i < mTaskGroups.Length(); ++i) {
|
for (size_t i = 0; i < mTaskGroups.Length(); ++i) {
|
||||||
if (mTaskGroups[i]->mThread == aThread) {
|
if (mTaskGroups[i]->mThread == aThread) {
|
||||||
DispatchTaskGroup(Move(mTaskGroups[i]));
|
nsresult rv2 = DispatchTaskGroup(Move(mTaskGroups[i]));
|
||||||
|
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv2)) && NS_SUCCEEDED(rv)) {
|
||||||
|
// We should try our best to call DispatchTaskGroup() as much as
|
||||||
|
// possible and return an error if any of DispatchTaskGroup() calls
|
||||||
|
// failed.
|
||||||
|
rv = rv2;
|
||||||
|
}
|
||||||
|
|
||||||
mTaskGroups.RemoveElementAt(i--);
|
mTaskGroups.RemoveElementAt(i--);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -169,7 +175,7 @@ private:
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit PerThreadTaskGroup(AbstractThread* aThread)
|
explicit PerThreadTaskGroup(AbstractThread* aThread)
|
||||||
: mThread(aThread), mFailureHandling(AbstractThread::DontAssertDispatchSuccess)
|
: mThread(aThread)
|
||||||
{
|
{
|
||||||
MOZ_COUNT_CTOR(PerThreadTaskGroup);
|
MOZ_COUNT_CTOR(PerThreadTaskGroup);
|
||||||
}
|
}
|
||||||
|
@ -179,7 +185,6 @@ private:
|
||||||
RefPtr<AbstractThread> mThread;
|
RefPtr<AbstractThread> mThread;
|
||||||
nsTArray<nsCOMPtr<nsIRunnable>> mStateChangeTasks;
|
nsTArray<nsCOMPtr<nsIRunnable>> mStateChangeTasks;
|
||||||
nsTArray<nsCOMPtr<nsIRunnable>> mRegularTasks;
|
nsTArray<nsCOMPtr<nsIRunnable>> mRegularTasks;
|
||||||
AbstractThread::DispatchFailureHandling mFailureHandling;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class TaskGroupRunnable : public Runnable
|
class TaskGroupRunnable : public Runnable
|
||||||
|
@ -250,15 +255,14 @@ private:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DispatchTaskGroup(UniquePtr<PerThreadTaskGroup> aGroup)
|
nsresult DispatchTaskGroup(UniquePtr<PerThreadTaskGroup> aGroup)
|
||||||
{
|
{
|
||||||
RefPtr<AbstractThread> thread = aGroup->mThread;
|
RefPtr<AbstractThread> thread = aGroup->mThread;
|
||||||
|
|
||||||
AbstractThread::DispatchFailureHandling failureHandling = aGroup->mFailureHandling;
|
|
||||||
AbstractThread::DispatchReason reason = mIsTailDispatcher ? AbstractThread::TailDispatch
|
AbstractThread::DispatchReason reason = mIsTailDispatcher ? AbstractThread::TailDispatch
|
||||||
: AbstractThread::NormalDispatch;
|
: AbstractThread::NormalDispatch;
|
||||||
nsCOMPtr<nsIRunnable> r = new TaskGroupRunnable(Move(aGroup));
|
nsCOMPtr<nsIRunnable> r = new TaskGroupRunnable(Move(aGroup));
|
||||||
thread->Dispatch(r.forget(), failureHandling, reason);
|
return thread->Dispatch(r.forget(), reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Direct tasks. We use a Maybe<> because (a) this class is hot, (b)
|
// Direct tasks. We use a Maybe<> because (a) this class is hot, (b)
|
||||||
|
|
|
@ -39,7 +39,6 @@ public:
|
||||||
nsCOMPtr<nsIRunnable> runnable = aEvent;
|
nsCOMPtr<nsIRunnable> runnable = aEvent;
|
||||||
MonitorAutoLock mon(mTaskQueue->mQueueMonitor);
|
MonitorAutoLock mon(mTaskQueue->mQueueMonitor);
|
||||||
return mTaskQueue->DispatchLocked(/* passed by ref */runnable,
|
return mTaskQueue->DispatchLocked(/* passed by ref */runnable,
|
||||||
DontAssertDispatchSuccess,
|
|
||||||
NormalDispatch);
|
NormalDispatch);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,7 +105,6 @@ TaskQueue::TailDispatcher()
|
||||||
// See Dispatch() in TaskQueue.h for more details.
|
// See Dispatch() in TaskQueue.h for more details.
|
||||||
nsresult
|
nsresult
|
||||||
TaskQueue::DispatchLocked(nsCOMPtr<nsIRunnable>& aRunnable,
|
TaskQueue::DispatchLocked(nsCOMPtr<nsIRunnable>& aRunnable,
|
||||||
DispatchFailureHandling aFailureHandling,
|
|
||||||
DispatchReason aReason)
|
DispatchReason aReason)
|
||||||
{
|
{
|
||||||
mQueueMonitor.AssertCurrentThreadOwns();
|
mQueueMonitor.AssertCurrentThreadOwns();
|
||||||
|
@ -116,8 +114,7 @@ TaskQueue::DispatchLocked(nsCOMPtr<nsIRunnable>& aRunnable,
|
||||||
|
|
||||||
AbstractThread* currentThread;
|
AbstractThread* currentThread;
|
||||||
if (aReason != TailDispatch && (currentThread = GetCurrent()) && RequiresTailDispatch(currentThread)) {
|
if (aReason != TailDispatch && (currentThread = GetCurrent()) && RequiresTailDispatch(currentThread)) {
|
||||||
currentThread->TailDispatcher().AddTask(this, aRunnable.forget(), aFailureHandling);
|
return currentThread->TailDispatcher().AddTask(this, aRunnable.forget());
|
||||||
return NS_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mTasks.push(aRunnable.forget());
|
mTasks.push(aRunnable.forget());
|
||||||
|
|
|
@ -61,20 +61,14 @@ public:
|
||||||
|
|
||||||
TaskQueue* AsTaskQueue() override { return this; }
|
TaskQueue* AsTaskQueue() override { return this; }
|
||||||
|
|
||||||
nsresult Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
MOZ_MUST_USE nsresult
|
||||||
DispatchFailureHandling aFailureHandling = AssertDispatchSuccess,
|
Dispatch(already_AddRefed<nsIRunnable> aRunnable,
|
||||||
DispatchReason aReason = NormalDispatch) override
|
DispatchReason aReason = NormalDispatch) override
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIRunnable> r = aRunnable;
|
nsCOMPtr<nsIRunnable> r = aRunnable;
|
||||||
{
|
{
|
||||||
MonitorAutoLock mon(mQueueMonitor);
|
MonitorAutoLock mon(mQueueMonitor);
|
||||||
nsresult rv = DispatchLocked(/* passed by ref */r, aFailureHandling, aReason);
|
return DispatchLocked(/* passed by ref */r, aReason);
|
||||||
#if defined(DEBUG) || !defined(RELEASE_OR_BETA) || defined(EARLY_BETA_OR_EARLIER)
|
|
||||||
if (NS_FAILED(rv) && aFailureHandling == AssertDispatchSuccess) {
|
|
||||||
MOZ_CRASH_UNSAFE_PRINTF("%s: Dispatch failed. rv=%x", mName, uint32_t(rv));
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
// If the ownership of |r| is not transferred in DispatchLocked() due to
|
// If the ownership of |r| is not transferred in DispatchLocked() due to
|
||||||
// dispatch failure, it will be deleted here outside the lock. We do so
|
// dispatch failure, it will be deleted here outside the lock. We do so
|
||||||
|
@ -121,7 +115,6 @@ protected:
|
||||||
void AwaitIdleLocked();
|
void AwaitIdleLocked();
|
||||||
|
|
||||||
nsresult DispatchLocked(nsCOMPtr<nsIRunnable>& aRunnable,
|
nsresult DispatchLocked(nsCOMPtr<nsIRunnable>& aRunnable,
|
||||||
DispatchFailureHandling aFailureHandling,
|
|
||||||
DispatchReason aReason = NormalDispatch);
|
DispatchReason aReason = NormalDispatch);
|
||||||
|
|
||||||
void MaybeResolveShutdown()
|
void MaybeResolveShutdown()
|
||||||
|
|
Загрузка…
Ссылка в новой задаче