From d45ddf9078c7f0f6b0d6e0e4edbe1f35f77af171 Mon Sep 17 00:00:00 2001 From: JW Wang Date: Thu, 11 May 2017 01:30:12 +0800 Subject: [PATCH] Bug 1362910. P1 - enable move when IsExclusive is true. r=gerald When IsExclusive is true, there is at most only one consumer. So it is safe to move the ResolveOrRejectValue stored in the promise. MozReview-Commit-ID: ED9fFr7TkvN --HG-- extra : rebase_source : 57c6732279a2c76fc21c3e7bad17d70f9cd0834a extra : intermediate-source : c55836b6708150e88c2ca3a804c2cf2fbcf79990 extra : source : 3285b59746e994283e101cc10267d3a642c96ab3 --- xpcom/threads/MozPromise.h | 46 +++++++++++++++++++++++++------------- 1 file changed, 30 insertions(+), 16 deletions(-) diff --git a/xpcom/threads/MozPromise.h b/xpcom/threads/MozPromise.h index e7ef4ecd658c..f6cb8ee5e430 100644 --- a/xpcom/threads/MozPromise.h +++ b/xpcom/threads/MozPromise.h @@ -133,6 +133,15 @@ class MozPromise : public MozPromiseRefcountable { static const uint32_t sMagic = 0xcecace11; + // Return a |T&&| to enable move when IsExclusive is true or + // a |const T&| to enforce copy otherwise. + template ::Type> + static R MaybeMove(T& aX) + { + return static_cast(aX); + } + public: typedef ResolveValueT ResolveValueType; typedef RejectValueT RejectValueType; @@ -449,9 +458,9 @@ protected: } protected: - virtual already_AddRefed DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) = 0; + virtual already_AddRefed DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) = 0; - void DoResolveOrReject(const ResolveOrRejectValue& aValue) + void DoResolveOrReject(ResolveOrRejectValue& aValue) { PROMISE_ASSERT(mMagic1 == sMagic && mMagic2 == sMagic); MOZ_DIAGNOSTIC_ASSERT(mResponseTarget->IsCurrentThreadIn()); @@ -549,13 +558,15 @@ protected: } protected: - already_AddRefed DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override + already_AddRefed DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override { RefPtr completion; if (aValue.IsResolve()) { - completion = InvokeCallbackMethod(mThisVal.get(), mResolveMethod, aValue.ResolveValue()); + completion = InvokeCallbackMethod( + mThisVal.get(), mResolveMethod, MaybeMove(aValue.ResolveValue())); } else { - completion = InvokeCallbackMethod(mThisVal.get(), mRejectMethod, aValue.RejectValue()); + completion = InvokeCallbackMethod( + mThisVal.get(), mRejectMethod, MaybeMove(aValue.RejectValue())); } // Null out mThisVal after invoking the callback so that any references are @@ -598,10 +609,10 @@ protected: } protected: - already_AddRefed DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override + already_AddRefed DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override { - RefPtr completion = - InvokeCallbackMethod(mThisVal.get(), mResolveRejectMethod, aValue); + RefPtr completion = InvokeCallbackMethod( + mThisVal.get(), mResolveRejectMethod, MaybeMove(aValue)); // Null out mThisVal after invoking the callback so that any references are // released predictably on the dispatch thread. Otherwise, it would be @@ -645,7 +656,7 @@ protected: } protected: - already_AddRefed DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override + already_AddRefed DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override { // Note: The usage of InvokeCallbackMethod here requires that // ResolveFunction/RejectFunction are capture-lambdas (i.e. anonymous @@ -654,9 +665,11 @@ protected: // just capturing something. RefPtr completion; if (aValue.IsResolve()) { - completion = InvokeCallbackMethod(mResolveFunction.ptr(), &ResolveFunction::operator(), aValue.ResolveValue()); + completion = InvokeCallbackMethod(mResolveFunction.ptr(), + &ResolveFunction::operator(), MaybeMove(aValue.ResolveValue())); } else { - completion = InvokeCallbackMethod(mRejectFunction.ptr(), &RejectFunction::operator(), aValue.RejectValue()); + completion = InvokeCallbackMethod(mRejectFunction.ptr(), + &RejectFunction::operator(), MaybeMove(aValue.RejectValue())); } // Destroy callbacks after invocation so that any references in closures are @@ -700,7 +713,7 @@ protected: } protected: - already_AddRefed DoResolveOrRejectInternal(const ResolveOrRejectValue& aValue) override + already_AddRefed DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override { // Note: The usage of InvokeCallbackMethod here requires that // ResolveRejectFunction is capture-lambdas (i.e. anonymous @@ -710,7 +723,7 @@ protected: RefPtr completion = InvokeCallbackMethod(mResolveRejectFunction.ptr(), &ResolveRejectFunction::operator(), - aValue); + MaybeMove(aValue)); // Destroy callbacks after invocation so that any references in closures are // released predictably on the dispatch thread. Otherwise, they would be @@ -950,7 +963,8 @@ public: protected: bool IsPending() const { return mValue.IsNothing(); } - const ResolveOrRejectValue& Value() const + + ResolveOrRejectValue& Value() { // This method should only be called once the value has stabilized. As // such, we don't need to acquire the lock here. @@ -976,9 +990,9 @@ protected: { MOZ_ASSERT(!IsPending()); if (mValue.IsResolve()) { - aOther->Resolve(mValue.ResolveValue(), ""); + aOther->Resolve(MaybeMove(mValue.ResolveValue()), ""); } else { - aOther->Reject(mValue.RejectValue(), ""); + aOther->Reject(MaybeMove(mValue.RejectValue()), ""); } }