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
Родитель 7c0de4212e
Коммит 652ca5c482
2 изменённых файлов: 68 добавлений и 1 удалений

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

@ -23,5 +23,18 @@ DispatchMediaPromiseRunnable(nsIEventTarget* aEventTarget, nsIRunnable* aRunnabl
return aEventTarget->Dispatch(aRunnable, NS_DISPATCH_NORMAL); 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 } // namespace mozilla

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

@ -37,6 +37,11 @@ namespace detail {
nsresult DispatchMediaPromiseRunnable(MediaTaskQueue* aQueue, nsIRunnable* aRunnable); nsresult DispatchMediaPromiseRunnable(MediaTaskQueue* aQueue, nsIRunnable* aRunnable);
nsresult DispatchMediaPromiseRunnable(nsIEventTarget* aTarget, nsIRunnable* aRunnable); nsresult DispatchMediaPromiseRunnable(nsIEventTarget* aTarget, nsIRunnable* aRunnable);
#ifdef DEBUG
void AssertOnThread(MediaTaskQueue* aQueue);
void AssertOnThread(nsIEventTarget* aTarget);
#endif
} // namespace detail } // namespace detail
/* /*
@ -85,9 +90,26 @@ public:
{ {
public: public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Consumer) 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: protected:
Consumer() {} Consumer() : mComplete(false), mDisconnected(false) {}
virtual ~Consumer() {} virtual ~Consumer() {}
bool mComplete;
bool mDisconnected;
}; };
protected: protected:
@ -217,9 +239,22 @@ protected:
MOZ_ASSERT(NS_SUCCEEDED(rv)); 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: protected:
virtual void DoResolve(ResolveValueType aResolveValue) MOZ_OVERRIDE 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); InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aResolveValue);
// Null these out after invoking the callback so that any references are // Null these out after invoking the callback so that any references are
@ -232,6 +267,11 @@ protected:
virtual void DoReject(RejectValueType aRejectValue) MOZ_OVERRIDE 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); InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aRejectValue);
// Null these out after invoking the callback so that any references are // Null these out after invoking the callback so that any references are
@ -471,6 +511,20 @@ public:
mConsumer = nullptr; 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; } bool Exists() { return !!mConsumer; }
private: private: