Bug 1126465 - Implement the ability to disconnect outstanding promises. r=mattwoodrow

This commit is contained in:
Bobby Holley 2015-01-29 22:11:11 -08:00
parent 5efebfb4df
commit 00b5f4be82
2 changed files with 68 additions and 1 deletions

View File

@ -23,5 +23,18 @@ DispatchMediaPromiseRunnable(nsIEventTarget* aEventTarget, nsIRunnable* aRunnabl
return aEventTarget->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
}
void
AssertOnThread(MediaTaskQueue* aQueue)
{
MOZ_ASSERT(aQueue->IsCurrentThreadIn());
}
void AssertOnThread(nsIEventTarget* aTarget)
{
nsCOMPtr<nsIThread> targetThread = do_QueryInterface(aTarget);
MOZ_ASSERT(targetThread, "Don't know how to deal with threadpools etc here");
MOZ_ASSERT(NS_GetCurrentThread() == targetThread);
}
}
} // namespace mozilla

View File

@ -37,6 +37,11 @@ namespace detail {
nsresult DispatchMediaPromiseRunnable(MediaTaskQueue* aQueue, nsIRunnable* aRunnable);
nsresult DispatchMediaPromiseRunnable(nsIEventTarget* aTarget, nsIRunnable* aRunnable);
#ifdef DEBUG
void AssertOnThread(MediaTaskQueue* aQueue);
void AssertOnThread(nsIEventTarget* aTarget);
#endif
} // namespace detail
/*
@ -85,9 +90,26 @@ public:
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Consumer)
void Disconnect()
{
AssertOnDispatchThread();
MOZ_RELEASE_ASSERT(!mComplete);
mDisconnected = true;
}
#ifdef DEBUG
virtual void AssertOnDispatchThread() = 0;
#else
void AssertOnDispatchThread() {}
#endif
protected:
Consumer() {}
Consumer() : mComplete(false), mDisconnected(false) {}
virtual ~Consumer() {}
bool mComplete;
bool mDisconnected;
};
protected:
@ -217,9 +239,22 @@ protected:
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
#ifdef DEBUG
// Can't mark MOZ_OVERRIDE due to bug in clang builders we use for osx b2g desktop. :-(
virtual void AssertOnDispatchThread()
{
detail::AssertOnThread(mResponseTarget);
}
#endif
protected:
virtual void DoResolve(ResolveValueType aResolveValue) MOZ_OVERRIDE
{
Consumer::mComplete = true;
if (Consumer::mDisconnected) {
PROMISE_LOG("ThenValue::DoResolve disconnected - bailing out [this=%p]", this);
return;
}
InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aResolveValue);
// Null these out after invoking the callback so that any references are
@ -232,6 +267,11 @@ protected:
virtual void DoReject(RejectValueType aRejectValue) MOZ_OVERRIDE
{
Consumer::mComplete = true;
if (Consumer::mDisconnected) {
PROMISE_LOG("ThenValue::DoReject disconnected - bailing out [this=%p]", this);
return;
}
InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aRejectValue);
// Null these out after invoking the callback so that any references are
@ -471,6 +511,20 @@ public:
mConsumer = nullptr;
}
// Disconnects and forgets an outstanding promise. The resolve/reject methods
// will never be called.
void Disconnect() {
MOZ_ASSERT(Exists());
mConsumer->Disconnect();
mConsumer = nullptr;
}
void DisconnectIfExists() {
if (Exists()) {
Disconnect();
}
}
bool Exists() { return !!mConsumer; }
private: