From fbaf0bb26397aa498eb9156f06d5a6fe34dd7dd8 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:14:29 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- xpcom/threads/MozPromise.h | 200 +++++++++++++++++++-------------------------- 1 file changed, 85 insertions(+), 115 deletions(-) (limited to 'xpcom/threads/MozPromise.h') diff --git a/xpcom/threads/MozPromise.h b/xpcom/threads/MozPromise.h index f17e085c2f..af4ac657fd 100644 --- a/xpcom/threads/MozPromise.h +++ b/xpcom/threads/MozPromise.h @@ -82,24 +82,22 @@ struct MethodTrait : MethodTraitsHelper> {}; } // namespace detail -template -using TakesArgument = - std::integral_constant::ArgSize != 0>; +template +using MethodReturnType = typename detail::MethodTrait::ReturnType; -template -using ReturnTypeIs = - std::is_convertible::ReturnType, - TargetType>; +template +constexpr bool TakesAnyArguments = + detail::MethodTrait::ArgSize != 0; template class MozPromise; -template -struct IsMozPromise : std::false_type {}; +template +constexpr bool IsMozPromise = false; template -struct IsMozPromise> - : std::true_type {}; +constexpr bool + IsMozPromise> = true; /* * A promise manages an asynchronous request that may or may not be able to be @@ -176,8 +174,8 @@ class MozPromise : public MozPromiseBase { } public: - typedef ResolveValueT ResolveValueType; - typedef RejectValueT RejectValueType; + using ResolveValueType = ResolveValueT; + using RejectValueType = RejectValueT; class ResolveOrRejectValue { public: template @@ -288,12 +286,10 @@ class MozPromise : public MozPromiseBase { return p; } - typedef MozPromise, RejectValueType, - IsExclusive> - AllPromiseType; - - typedef MozPromise, bool, IsExclusive> - AllSettledPromiseType; + using AllPromiseType = MozPromise, + RejectValueType, IsExclusive>; + using AllSettledPromiseType = + MozPromise, bool, IsExclusive>; private: class AllPromiseHolder : public MozPromiseRefcountable { @@ -350,17 +346,17 @@ class MozPromise : public MozPromiseBase { // Trying to pass ResolveOrRejectValue by value fails static analysis checks, // so we need to use either a const& or an rvalue reference, depending on // whether IsExclusive is true or not. - typedef std::conditional_t - ResolveOrRejectValueParam; + using ResolveOrRejectValueParam = + std::conditional_t; - typedef std::conditional_t - ResolveValueTypeParam; + using ResolveValueTypeParam = + std::conditional_t; - typedef std::conditional_t - RejectValueTypeParam; + using RejectValueTypeParam = + std::conditional_t; class AllSettledPromiseHolder : public MozPromiseRefcountable { public: @@ -648,15 +644,15 @@ class MozPromise : public MozPromiseBase { * make the resolve/reject value argument "optional". */ template - static std::enable_if_t::value, - typename detail::MethodTrait::ReturnType> + static std::enable_if_t, + MethodReturnType> InvokeMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue) { return (aThisVal->*aMethod)(std::forward(aValue)); } template - static std::enable_if_t::value, - typename detail::MethodTrait::ReturnType> + static std::enable_if_t, + MethodReturnType> InvokeMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue) { return (aThisVal->*aMethod)(); } @@ -697,18 +693,14 @@ class MozPromise : public MozPromiseBase { : public ThenValueBase { friend class ThenCommand; - using R1 = typename RemoveSmartPointer< - typename detail::MethodTrait::ReturnType>::Type; - using R2 = typename RemoveSmartPointer< - typename detail::MethodTrait::ReturnType>::Type; - using SupportChaining = - std::integral_constant::value && - std::is_same_v>; + using R1 = RemoveSmartPointer>; + using R2 = RemoveSmartPointer>; + constexpr static bool SupportChaining = + IsMozPromise && std::is_same_v; // Fall back to MozPromise when promise chaining is not supported to make // code compile. - using PromiseType = - std::conditional_t; + using PromiseType = std::conditional_t; public: ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal, @@ -736,13 +728,13 @@ class MozPromise : public MozPromiseBase { void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override { if (aValue.IsResolve()) { - InvokeCallbackMethod( - mThisVal.get(), mResolveMethod, MaybeMove(aValue.ResolveValue()), - std::move(mCompletionPromise)); + InvokeCallbackMethod(mThisVal.get(), mResolveMethod, + MaybeMove(aValue.ResolveValue()), + std::move(mCompletionPromise)); } else { - InvokeCallbackMethod( - mThisVal.get(), mRejectMethod, MaybeMove(aValue.RejectValue()), - std::move(mCompletionPromise)); + InvokeCallbackMethod(mThisVal.get(), mRejectMethod, + MaybeMove(aValue.RejectValue()), + std::move(mCompletionPromise)); } // Null out mThisVal after invoking the callback so that any references @@ -764,15 +756,12 @@ class MozPromise : public MozPromiseBase { class ThenValue : public ThenValueBase { friend class ThenCommand; - using R1 = typename RemoveSmartPointer::ReturnType>::Type; - using SupportChaining = - std::integral_constant::value>; + using R1 = RemoveSmartPointer>; + constexpr static bool SupportChaining = IsMozPromise; // Fall back to MozPromise when promise chaining is not supported to make // code compile. - using PromiseType = - std::conditional_t; + using PromiseType = std::conditional_t; public: ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal, @@ -798,7 +787,7 @@ class MozPromise : public MozPromiseBase { } void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override { - InvokeCallbackMethod( + InvokeCallbackMethod( mThisVal.get(), mResolveRejectMethod, MaybeMove(aValue), std::move(mCompletionPromise)); @@ -822,18 +811,14 @@ class MozPromise : public MozPromiseBase { class ThenValue : public ThenValueBase { friend class ThenCommand; - using R1 = typename RemoveSmartPointer< - typename detail::MethodTrait::ReturnType>::Type; - using R2 = typename RemoveSmartPointer< - typename detail::MethodTrait::ReturnType>::Type; - using SupportChaining = - std::integral_constant::value && - std::is_same_v>; + using R1 = RemoveSmartPointer>; + using R2 = RemoveSmartPointer>; + constexpr static bool SupportChaining = + IsMozPromise && std::is_same_v; // Fall back to MozPromise when promise chaining is not supported to make // code compile. - using PromiseType = - std::conditional_t; + using PromiseType = std::conditional_t; public: ThenValue(nsISerialEventTarget* aResponseTarget, @@ -867,11 +852,11 @@ class MozPromise : public MozPromiseBase { // easily. We could fix this if need be, though it's quite easy to work // around by just capturing something. if (aValue.IsResolve()) { - InvokeCallbackMethod( + InvokeCallbackMethod( mResolveFunction.ptr(), &ResolveFunction::operator(), MaybeMove(aValue.ResolveValue()), std::move(mCompletionPromise)); } else { - InvokeCallbackMethod( + InvokeCallbackMethod( mRejectFunction.ptr(), &RejectFunction::operator(), MaybeMove(aValue.RejectValue()), std::move(mCompletionPromise)); } @@ -896,15 +881,12 @@ class MozPromise : public MozPromiseBase { class ThenValue : public ThenValueBase { friend class ThenCommand; - using R1 = typename RemoveSmartPointer< - typename detail::MethodTrait::ReturnType>::Type; - using SupportChaining = - std::integral_constant::value>; + using R1 = RemoveSmartPointer>; + constexpr static bool SupportChaining = IsMozPromise; // Fall back to MozPromise when promise chaining is not supported to make // code compile. - using PromiseType = - std::conditional_t; + using PromiseType = std::conditional_t; public: ThenValue(nsISerialEventTarget* aResponseTarget, @@ -935,7 +917,7 @@ class MozPromise : public MozPromiseBase { // classes with ::operator()), since it allows us to share code more // easily. We could fix this if need be, though it's quite easy to work // around by just capturing something. - InvokeCallbackMethod( + InvokeCallbackMethod( mResolveRejectFunction.ptr(), &ResolveRejectFunction::operator(), MaybeMove(aValue), std::move(mCompletionPromise)); @@ -998,7 +980,7 @@ class MozPromise : public MozPromiseBase { MozPromise* aReceiver) : mCallSite(aCallSite), mThenValue(aThenValue), mReceiver(aReceiver) {} - ThenCommand(ThenCommand&& aOther) = default; + ThenCommand(ThenCommand&& aOther) noexcept = default; public: ~ThenCommand() { @@ -1013,7 +995,7 @@ class MozPromise : public MozPromiseBase { // p->Then(thread2, ...); operator RefPtr() { static_assert( - ThenValueType::SupportChaining::value, + ThenValueType::SupportChaining, "The resolve/reject callback needs to return a RefPtr " "in order to do promise chaining."); @@ -1336,12 +1318,18 @@ class MozPromise::Private }; // A generic promise type that does the trick for simple use cases. -typedef MozPromise GenericPromise; +// +// Vaguely deprecated: prefer explicitly naming the resolve- and reject-type. +// Additionally, prefer `mozilla::Ok` as the resolve-type if the boolean's value +// is irrelevant. +using GenericPromise = MozPromise; // A generic, non-exclusive promise type that does the trick for simple use // cases. -typedef MozPromise - GenericNonExclusivePromise; +// +// Vaguely deprecated, as above. +using GenericNonExclusivePromise = + MozPromise; /* * Class to encapsulate a promise for a particular role. Use this as the member @@ -1352,8 +1340,9 @@ class MozPromiseHolderBase { public: MozPromiseHolderBase() = default; - MozPromiseHolderBase(MozPromiseHolderBase&& aOther) = default; - MozPromiseHolderBase& operator=(MozPromiseHolderBase&& aOther) = default; + MozPromiseHolderBase(MozPromiseHolderBase&& aOther) noexcept = default; + MozPromiseHolderBase& operator=(MozPromiseHolderBase&& aOther) noexcept = + default; ~MozPromiseHolderBase() { MOZ_ASSERT(!mPromise); } @@ -1511,8 +1500,8 @@ class MozPromiseRequestHolder { // will never be called. void Disconnect() { MOZ_ASSERT(Exists()); - mRequest->Disconnect(); - mRequest = nullptr; + RefPtr request = std::move(mRequest); + request->Disconnect(); } void DisconnectIfExists() { @@ -1700,30 +1689,26 @@ class ProxyFunctionRunnable : public CancelableRunnable { UniquePtr mFunction; }; -// Note: The following struct and function are not for public consumption (yet?) -// as we would prefer all calls to pass on-the-spot lambdas (or at least moved -// function objects). They could be moved outside of detail if really needed. +template +constexpr static bool IsRefPtrMozPromise = false; +template +constexpr static bool IsRefPtrMozPromise>> = true; -// We prefer getting function objects by non-lvalue-ref (to avoid copying them -// and their captures). This struct is a tag that allows the use of objects -// through lvalue-refs where necessary. -struct AllowInvokeAsyncFunctionLVRef {}; +} // namespace detail -// Invoke a function object (e.g., lambda or std/mozilla::function) -// asynchronously; note that the object will be copied if provided by -// lvalue-ref. Return a promise that the function should eventually resolve or -// reject. +// Invoke a function object (e.g., lambda) asynchronously. +// Return a promise that the function should eventually resolve or reject. template static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName, - AllowInvokeAsyncFunctionLVRef, Function&& aFunction) - -> decltype(aFunction()) { - static_assert( - IsRefcountedSmartPointer::value && - IsMozPromise< - typename RemoveSmartPointer::Type>::value, - "Function object must return RefPtr"); + Function&& aFunction) -> decltype(aFunction()) { + static_assert(!std::is_lvalue_reference_v, + "Function object must not be passed by lvalue-ref (to avoid " + "unplanned copies); Consider move()ing the object."); + + static_assert(detail::IsRefPtrMozPromise, + "Function object must return RefPtr"); MOZ_ASSERT(aTarget); - typedef typename RemoveSmartPointer::Type PromiseType; + typedef RemoveSmartPointer PromiseType; typedef detail::ProxyFunctionRunnable ProxyRunnableType; @@ -1733,21 +1718,6 @@ static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName, return p; } -} // namespace detail - -// Invoke a function object (e.g., lambda) asynchronously. -// Return a promise that the function should eventually resolve or reject. -template -static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName, - Function&& aFunction) -> decltype(aFunction()) { - static_assert(!std::is_lvalue_reference_v, - "Function object must not be passed by lvalue-ref (to avoid " - "unplanned copies); Consider move()ing the object."); - return detail::InvokeAsync(aTarget, aCallerName, - detail::AllowInvokeAsyncFunctionLVRef(), - std::forward(aFunction)); -} - # undef PROMISE_LOG # undef PROMISE_ASSERT # undef PROMISE_DEBUG -- cgit v1.2.3