From 40a355a42d4a9444dc753c04c6608dade2f06a23 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:13:27 +0200 Subject: Adding upstream version 125.0.1. Signed-off-by: Daniel Baumann --- xpcom/threads/MozPromise.h | 200 +++++++++++-------------- xpcom/threads/Mutex.h | 4 +- xpcom/threads/nsThreadManager.cpp | 6 +- xpcom/threads/nsThreadUtils.h | 301 ++++++++++++++------------------------ 4 files changed, 201 insertions(+), 310 deletions(-) (limited to 'xpcom/threads') 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 diff --git a/xpcom/threads/Mutex.h b/xpcom/threads/Mutex.h index 5116f1d7c3..8edb6ee773 100644 --- a/xpcom/threads/Mutex.h +++ b/xpcom/threads/Mutex.h @@ -227,7 +227,7 @@ class MOZ_RAII MOZ_SCOPED_CAPABILITY BaseAutoLock { public: /** * Constructor - * The constructor aquires the given lock. The destructor + * The constructor acquires the given lock. The destructor * releases the lock. * * @param aLock A valid mozilla::Mutex* returned by @@ -343,7 +343,7 @@ class MOZ_RAII MOZ_SCOPED_CAPABILITY ReleasableBaseAutoLock { public: /** * Constructor - * The constructor aquires the given lock. The destructor + * The constructor acquires the given lock. The destructor * releases the lock. * * @param aLock A valid mozilla::Mutex& returned by diff --git a/xpcom/threads/nsThreadManager.cpp b/xpcom/threads/nsThreadManager.cpp index 805be6ee64..3ea324a6c6 100644 --- a/xpcom/threads/nsThreadManager.cpp +++ b/xpcom/threads/nsThreadManager.cpp @@ -672,11 +672,11 @@ void AutoNestedEventLoopAnnotation::AnnotateXPCOMSpinEventLoopStack( if (aStack.Length() > 0) { nsCString prefixedStack(XRE_GetProcessTypeString()); prefixedStack += ": "_ns + aStack; - CrashReporter::AnnotateCrashReport( + CrashReporter::RecordAnnotationNSCString( CrashReporter::Annotation::XPCOMSpinEventLoopStack, prefixedStack); } else { - CrashReporter::AnnotateCrashReport( - CrashReporter::Annotation::XPCOMSpinEventLoopStack, ""_ns); + CrashReporter::UnrecordAnnotation( + CrashReporter::Annotation::XPCOMSpinEventLoopStack); } } diff --git a/xpcom/threads/nsThreadUtils.h b/xpcom/threads/nsThreadUtils.h index 72041da295..755ec21c95 100644 --- a/xpcom/threads/nsThreadUtils.h +++ b/xpcom/threads/nsThreadUtils.h @@ -562,71 +562,40 @@ using RunnableFunctionImpl = namespace detail { -template -struct IsRefcountedSmartPointerHelper : std::false_type {}; - -template -struct IsRefcountedSmartPointerHelper> : std::true_type {}; - -template -struct IsRefcountedSmartPointerHelper> : std::true_type {}; - -} // namespace detail - template -struct IsRefcountedSmartPointer - : detail::IsRefcountedSmartPointerHelper> {}; - -namespace detail { - -template struct RemoveSmartPointerHelper { - typedef T Type; + using Type = T; }; -template -struct RemoveSmartPointerHelper> { - typedef Pointee Type; +template +struct RemoveSmartPointerHelper> { + using Type = T; }; -template -struct RemoveSmartPointerHelper> { - typedef Pointee Type; +template +struct RemoveSmartPointerHelper> { + using Type = T; }; -} // namespace detail - template -struct RemoveSmartPointer - : detail::RemoveSmartPointerHelper> {}; - -namespace detail { - -template struct RemoveRawOrSmartPointerHelper { - typedef T Type; -}; - -template -struct RemoveRawOrSmartPointerHelper { - typedef Pointee Type; + using Type = typename RemoveSmartPointerHelper::Type; }; -template -struct RemoveRawOrSmartPointerHelper> { - typedef Pointee Type; -}; - -template -struct RemoveRawOrSmartPointerHelper> { - typedef Pointee Type; +template +struct RemoveRawOrSmartPointerHelper { + using Type = T; }; } // namespace detail template -struct RemoveRawOrSmartPointer - : detail::RemoveRawOrSmartPointerHelper> {}; +using RemoveSmartPointer = + typename detail::RemoveSmartPointerHelper>::Type; + +template +using RemoveRawOrSmartPointer = + typename detail::RemoveRawOrSmartPointerHelper>::Type; } // namespace mozilla @@ -797,23 +766,22 @@ struct nsRunnableMethodTraits; template struct nsRunnableMethodTraits { - typedef typename mozilla::RemoveRawOrSmartPointer::Type class_type; + using class_type = mozilla::RemoveRawOrSmartPointer; static_assert(std::is_base_of::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod base_type; + using return_type = R; + using base_type = nsRunnableMethod; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; template struct nsRunnableMethodTraits { - typedef const typename mozilla::RemoveRawOrSmartPointer::Type - class_type; + using class_type = const mozilla::RemoveRawOrSmartPointer; static_assert(std::is_base_of::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod base_type; + using return_type = R; + using base_type = nsRunnableMethod; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; @@ -822,22 +790,22 @@ template struct nsRunnableMethodTraits { - typedef typename mozilla::RemoveRawOrSmartPointer::Type class_type; + using class_type = mozilla::RemoveRawOrSmartPointer; static_assert(std::is_base_of::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod base_type; + using return_type = R; + using base_type = nsRunnableMethod; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; template struct nsRunnableMethodTraits { - typedef typename mozilla::RemoveRawOrSmartPointer::Type class_type; + using class_type = mozilla::RemoveRawOrSmartPointer; static_assert(std::is_base_of::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod base_type; + using return_type = R; + using base_type = nsRunnableMethod; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; @@ -845,12 +813,11 @@ template struct nsRunnableMethodTraits { - typedef const typename mozilla::RemoveRawOrSmartPointer::Type - class_type; + using class_type = const mozilla::RemoveRawOrSmartPointer; static_assert(std::is_base_of::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod base_type; + using return_type = R; + using base_type = nsRunnableMethod; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; @@ -858,12 +825,11 @@ template struct nsRunnableMethodTraits { - typedef const typename mozilla::RemoveRawOrSmartPointer::Type - class_type; + using class_type = const mozilla::RemoveRawOrSmartPointer; static_assert(std::is_base_of::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod base_type; + using return_type = R; + using base_type = nsRunnableMethod; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; # endif @@ -880,19 +846,6 @@ struct IsParameterStorageClass : public std::false_type {}; // StoreXPassByY structs used to inform nsRunnableMethodArguments how to // store arguments, and how to pass them to the target method. -template -struct StoreCopyPassByValue { - using stored_type = std::decay_t; - typedef stored_type passed_type; - stored_type m; - template - MOZ_IMPLICIT StoreCopyPassByValue(A&& a) : m(std::forward(a)) {} - passed_type PassAsParameter() { return m; } -}; -template -struct IsParameterStorageClass> - : public std::true_type {}; - template struct StoreCopyPassByConstLRef { using stored_type = std::decay_t; @@ -906,19 +859,6 @@ template struct IsParameterStorageClass> : public std::true_type {}; -template -struct StoreCopyPassByLRef { - using stored_type = std::decay_t; - typedef stored_type& passed_type; - stored_type m; - template - MOZ_IMPLICIT StoreCopyPassByLRef(A&& a) : m(std::forward(a)) {} - passed_type PassAsParameter() { return m; } -}; -template -struct IsParameterStorageClass> : public std::true_type { -}; - template struct StoreCopyPassByRRef { using stored_type = std::decay_t; @@ -996,32 +936,6 @@ template struct IsParameterStorageClass> : public std::true_type {}; -template -struct StoreCopyPassByConstPtr { - typedef T stored_type; - typedef const T* passed_type; - stored_type m; - template - MOZ_IMPLICIT StoreCopyPassByConstPtr(A&& a) : m(std::forward(a)) {} - passed_type PassAsParameter() { return &m; } -}; -template -struct IsParameterStorageClass> - : public std::true_type {}; - -template -struct StoreCopyPassByPtr { - typedef T stored_type; - typedef T* passed_type; - stored_type m; - template - MOZ_IMPLICIT StoreCopyPassByPtr(A&& a) : m(std::forward(a)) {} - passed_type PassAsParameter() { return &m; } -}; -template -struct IsParameterStorageClass> : public std::true_type { -}; - namespace detail { template @@ -1035,94 +949,101 @@ template static auto HasRefCountMethodsTest(long) -> std::false_type; template -struct HasRefCountMethods : decltype(HasRefCountMethodsTest(0)) {}; - -template -struct NonnsISupportsPointerStorageClass - : std::conditional< - std::is_const_v, - StoreConstPtrPassByConstPtr>, - StorePtrPassByPtr> { - using Type = typename NonnsISupportsPointerStorageClass::conditional::type; +constexpr static bool HasRefCountMethods = + decltype(HasRefCountMethodsTest(0))::value; + +// Choose storage&passing strategy based on preferred storage type: +// - If IsParameterStorageClass::value is true, use as-is. +// - RC* -> StoreRefPtrPassByPtr :Store RefPtr, pass RC* +// ^^ RC quacks like a ref-counted type (i.e., has AddRef and Release methods) +// - const T* -> StoreConstPtrPassByConstPtr :Store const T*, pass const T* +// - T* -> StorePtrPassByPtr :Store T*, pass T*. +// - const T& -> StoreConstRefPassByConstLRef:Store const T&, pass const T&. +// - T& -> StoreRefPassByLRef :Store T&, pass T&. +// - T&& -> StoreCopyPassByRRef :Store T, pass std::move(T). +// - RefPtr, nsCOMPtr +// -> StoreRefPtrPassByPtr :Store RefPtr, pass T* +// - Other T -> StoreCopyPassByConstLRef :Store T, pass const T&. +// +// For anything less common, please use a lambda function rather than devising +// new parameter-storage classes. (In fact, consider doing that anyway.) + +template +struct OtherParameterStorage; + +// The `IsParameterStorageClass` and `RC*` cases must be handled separately (see +// `ParameterStorageHelper`, below) until we can use C++20 concepts. + +template +struct OtherParameterStorage { + using Type = StoreConstPtrPassByConstPtr; }; -template -struct PointerStorageClass - : std::conditional< - HasRefCountMethods::value, - StoreRefPtrPassByPtr, - typename NonnsISupportsPointerStorageClass::Type> { - using Type = typename PointerStorageClass::conditional::type; +template +struct OtherParameterStorage { + using Type = StorePtrPassByPtr; }; -template -struct LValueReferenceStorageClass - : std::conditional< - std::is_const_v, - StoreConstRefPassByConstLRef>, - StoreRefPassByLRef> { - using Type = typename LValueReferenceStorageClass::conditional::type; +template +struct OtherParameterStorage { + using Type = StoreConstRefPassByConstLRef; }; template -struct SmartPointerStorageClass - : std::conditional< - mozilla::IsRefcountedSmartPointer::value, - StoreRefPtrPassByPtr::Type>, - StoreCopyPassByConstLRef> { - using Type = typename SmartPointerStorageClass::conditional::type; +struct OtherParameterStorage { + using Type = StoreRefPassByLRef; }; template -struct NonLValueReferenceStorageClass - : std::conditional, - StoreCopyPassByRRef>, - typename SmartPointerStorageClass::Type> { - using Type = typename NonLValueReferenceStorageClass::conditional::type; +struct OtherParameterStorage> { + using Type = StoreRefPtrPassByPtr; }; template -struct NonPointerStorageClass - : std::conditional, - typename LValueReferenceStorageClass< - std::remove_reference_t>::Type, - typename NonLValueReferenceStorageClass::Type> { - using Type = typename NonPointerStorageClass::conditional::type; +struct OtherParameterStorage> { + using Type = StoreRefPtrPassByPtr; }; template -struct NonParameterStorageClass - : std::conditional< - std::is_pointer_v, - typename PointerStorageClass>::Type, - typename NonPointerStorageClass::Type> { - using Type = typename NonParameterStorageClass::conditional::type; +struct OtherParameterStorage { + using Type = StoreCopyPassByRRef; +}; + +template +struct OtherParameterStorage { + // This is good advice regardless of the types you're handling. + static_assert(!SFINAE1True::value, "please use a lambda function"); +}; + +// default impl. +template +struct OtherParameterStorage { + using Type = StoreCopyPassByConstLRef; +}; + +template ::value, + bool B = std::is_pointer_v && + HasRefCountMethods>> +struct ParameterStorageHelper; + +template +struct ParameterStorageHelper { + using Type = T; +}; + +template +struct ParameterStorageHelper { + using Type = StoreRefPtrPassByPtr>; +}; + +template +struct ParameterStorageHelper { + using Type = typename OtherParameterStorage>::Type; }; -// Choose storage&passing strategy based on preferred storage type: -// - If IsParameterStorageClass::value is true, use as-is. -// - RC* -> StoreRefPtrPassByPtr :Store RefPtr, pass RC* -// ^^ RC quacks like a ref-counted type (i.e., has AddRef and Release methods) -// - const T* -> StoreConstPtrPassByConstPtr :Store const T*, pass const T* -// - T* -> StorePtrPassByPtr :Store T*, pass T*. -// - const T& -> StoreConstRefPassByConstLRef:Store const T&, pass const T&. -// - T& -> StoreRefPassByLRef :Store T&, pass T&. -// - T&& -> StoreCopyPassByRRef :Store T, pass std::move(T). -// - RefPtr, nsCOMPtr -// -> StoreRefPtrPassByPtr :Store RefPtr, pass T* -// - Other T -> StoreCopyPassByConstLRef :Store T, pass const T&. -// Other available explicit options: -// - StoreCopyPassByValue :Store T, pass T. -// - StoreCopyPassByLRef :Store T, pass T& (of copy!) -// - StoreCopyPassByConstPtr :Store T, pass const T* -// - StoreCopyPassByPtr :Store T, pass T* (of copy!) -// Or create your own class with PassAsParameter() method, optional -// clean-up in destructor, and with associated IsParameterStorageClass<>. template -struct ParameterStorage - : std::conditional::value, T, - typename NonParameterStorageClass::Type> { - using Type = typename ParameterStorage::conditional::type; +struct ParameterStorage { + using Type = typename ParameterStorageHelper::Type; }; template -- cgit v1.2.3