Bug 1321250 - Add MozPromise::ThenPromise() for easier promise chaining. r=jya

MozReview-Commit-ID: 7J60CN0HbOW

--HG--
extra : rebase_source : d5fae5853c2c6c3197361db9c62424b6cbe9f593
extra : source : 8ab119efc0d23e9d919846489a0bdc9473d2fbd6
This commit is contained in:
JW Wang 2016-11-30 18:23:12 +08:00
parent 16e7762061
commit b49cd98e3b

View File

@ -332,14 +332,25 @@ protected:
RefPtr<MozPromise> mPromise;
};
explicit ThenValueBase(AbstractThread* aResponseTarget, const char* aCallSite)
: mResponseTarget(aResponseTarget), mCallSite(aCallSite) {}
ThenValueBase(AbstractThread* aResponseTarget,
const char* aCallSite,
bool aInitCompletionPromise = false)
: mResponseTarget(aResponseTarget)
, mCallSite(aCallSite)
, mInitCompletionPromise(aInitCompletionPromise)
{
if (mInitCompletionPromise) {
mCompletionPromise = new MozPromise::Private(
"<completion promise>", true /* aIsCompletionPromise */);
}
}
MozPromise* CompletionPromise() override
{
MOZ_DIAGNOSTIC_ASSERT(mResponseTarget->IsCurrentThreadIn());
MOZ_DIAGNOSTIC_ASSERT(mInitCompletionPromise ||
mResponseTarget->IsCurrentThreadIn());
MOZ_DIAGNOSTIC_ASSERT(!Request::mComplete);
if (!mCompletionPromise) {
if (!mInitCompletionPromise && !mCompletionPromise) {
mCompletionPromise = new MozPromise::Private(
"<completion promise>", true /* aIsCompletionPromise */);
}
@ -433,6 +444,10 @@ protected:
RefPtr<MozPromise> mCompletionPromise;
const char* mCallSite;
// True if mCompletionPromise should be initialized in the constructor
// to make CompletionPromise() thread-safe.
const bool mInitCompletionPromise;
};
/*
@ -484,8 +499,8 @@ protected:
public:
MethodThenValue(AbstractThread* aResponseTarget, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod,
const char* aCallSite)
: ThenValueBase(aResponseTarget, aCallSite)
const char* aCallSite, bool aInitCompletionPromise = false)
: ThenValueBase(aResponseTarget, aCallSite, aInitCompletionPromise)
, mThisVal(aThisVal)
, mResolveMethod(aResolveMethod)
, mRejectMethod(aRejectMethod) {}
@ -533,8 +548,9 @@ protected:
FunctionThenValue(AbstractThread* aResponseTarget,
ResolveFunction&& aResolveFunction,
RejectFunction&& aRejectFunction,
const char* aCallSite)
: ThenValueBase(aResponseTarget, aCallSite)
const char* aCallSite,
bool aInitCompletionPromise = false)
: ThenValueBase(aResponseTarget, aCallSite, aInitCompletionPromise)
{
mResolveFunction.emplace(Move(aResolveFunction));
mRejectFunction.emplace(Move(aRejectFunction));
@ -603,7 +619,7 @@ public:
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
RefPtr<Request> Then(AbstractThread* aResponseThread, const char* aCallSite, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
{
RefPtr<ThenValueBase> thenValue = new MethodThenValue<ThisType, ResolveMethodType, RejectMethodType>(
aResponseThread, aThisVal, aResolveMethod, aRejectMethod, aCallSite);
@ -613,7 +629,7 @@ public:
template<typename ResolveFunction, typename RejectFunction>
RefPtr<Request> Then(AbstractThread* aResponseThread, const char* aCallSite,
ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
{
RefPtr<ThenValueBase> thenValue = new FunctionThenValue<ResolveFunction, RejectFunction>(aResponseThread,
Move(aResolveFunction), Move(aRejectFunction), aCallSite);
@ -621,6 +637,41 @@ public:
return thenValue.forget(); // Implicit conversion from already_AddRefed<ThenValueBase> to RefPtr<Request>.
}
// Equivalent to Then(target, ...)->CompletionPromise()
// without the restriction that CompletionPromise() must be called on the
// |target| thread. So ThenPromise() can be called on any thread as Then().
// The syntax is close to JS promise and makes promise chaining easier
// where you can do: p->ThenPromise()->ThenPromise()->ThenPromise();
//
// Note you would have to call Then() instead when the result needs to be held
// by a MozPromiseRequestHolder for future disconnection.
//
// TODO: replace Then()->CompletionPromise() with ThenPromise() and
// stop exposing CompletionPromise() to the client code.
template<typename ThisType, typename ResolveMethodType, typename RejectMethodType>
MOZ_MUST_USE RefPtr<MozPromise>
ThenPromise(AbstractThread* aResponseThread, const char* aCallSite, ThisType* aThisVal,
ResolveMethodType aResolveMethod, RejectMethodType aRejectMethod)
{
using ThenType = MethodThenValue<ThisType, ResolveMethodType, RejectMethodType>;
RefPtr<ThenValueBase> thenValue = new ThenType(aResponseThread, aThisVal, aResolveMethod,
aRejectMethod, aCallSite, true /* aInitCompletionPromise */);
ThenInternal(aResponseThread, thenValue, aCallSite);
return thenValue->CompletionPromise();
}
template<typename ResolveFunction, typename RejectFunction>
MOZ_MUST_USE RefPtr<MozPromise>
ThenPromise(AbstractThread* aResponseThread, const char* aCallSite,
ResolveFunction&& aResolveFunction, RejectFunction&& aRejectFunction)
{
using ThenType = FunctionThenValue<ResolveFunction, RejectFunction>;
RefPtr<ThenValueBase> thenValue = new ThenType(aResponseThread, Move(aResolveFunction),
Move(aRejectFunction), aCallSite, true /* aInitCompletionPromise */);
ThenInternal(aResponseThread, thenValue, aCallSite);
return thenValue->CompletionPromise();
}
void ChainTo(already_AddRefed<Private> aChainedPromise, const char* aCallSite)
{
MutexAutoLock lock(mMutex);