diff options
Diffstat (limited to 'xpcom/threads/nsThreadUtils.h')
-rw-r--r-- | xpcom/threads/nsThreadUtils.h | 301 |
1 files changed, 111 insertions, 190 deletions
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 <typename CVRemoved> -struct IsRefcountedSmartPointerHelper : std::false_type {}; - -template <typename Pointee> -struct IsRefcountedSmartPointerHelper<RefPtr<Pointee>> : std::true_type {}; - -template <typename Pointee> -struct IsRefcountedSmartPointerHelper<nsCOMPtr<Pointee>> : std::true_type {}; - -} // namespace detail - template <typename T> -struct IsRefcountedSmartPointer - : detail::IsRefcountedSmartPointerHelper<std::remove_cv_t<T>> {}; - -namespace detail { - -template <typename T, typename CVRemoved> struct RemoveSmartPointerHelper { - typedef T Type; + using Type = T; }; -template <typename T, typename Pointee> -struct RemoveSmartPointerHelper<T, RefPtr<Pointee>> { - typedef Pointee Type; +template <typename T> +struct RemoveSmartPointerHelper<RefPtr<T>> { + using Type = T; }; -template <typename T, typename Pointee> -struct RemoveSmartPointerHelper<T, nsCOMPtr<Pointee>> { - typedef Pointee Type; +template <typename T> +struct RemoveSmartPointerHelper<nsCOMPtr<T>> { + using Type = T; }; -} // namespace detail - template <typename T> -struct RemoveSmartPointer - : detail::RemoveSmartPointerHelper<T, std::remove_cv_t<T>> {}; - -namespace detail { - -template <typename T, typename CVRemoved> struct RemoveRawOrSmartPointerHelper { - typedef T Type; -}; - -template <typename T, typename Pointee> -struct RemoveRawOrSmartPointerHelper<T, Pointee*> { - typedef Pointee Type; + using Type = typename RemoveSmartPointerHelper<T>::Type; }; -template <typename T, typename Pointee> -struct RemoveRawOrSmartPointerHelper<T, RefPtr<Pointee>> { - typedef Pointee Type; -}; - -template <typename T, typename Pointee> -struct RemoveRawOrSmartPointerHelper<T, nsCOMPtr<Pointee>> { - typedef Pointee Type; +template <typename T> +struct RemoveRawOrSmartPointerHelper<T*> { + using Type = T; }; } // namespace detail template <typename T> -struct RemoveRawOrSmartPointer - : detail::RemoveRawOrSmartPointerHelper<T, std::remove_cv_t<T>> {}; +using RemoveSmartPointer = + typename detail::RemoveSmartPointerHelper<std::remove_cv_t<T>>::Type; + +template <typename T> +using RemoveRawOrSmartPointer = + typename detail::RemoveRawOrSmartPointerHelper<std::remove_cv_t<T>>::Type; } // namespace mozilla @@ -797,23 +766,22 @@ struct nsRunnableMethodTraits; template <typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As> struct nsRunnableMethodTraits<PtrType, R (C::*)(As...), Owning, Kind> { - typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; + using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>; static_assert(std::is_base_of<C, class_type>::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod<C, R, Owning, Kind> base_type; + using return_type = R; + using base_type = nsRunnableMethod<C, R, Owning, Kind>; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; template <typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As> struct nsRunnableMethodTraits<PtrType, R (C::*)(As...) const, Owning, Kind> { - typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type - class_type; + using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>; static_assert(std::is_base_of<C, class_type>::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod<C, R, Owning, Kind> base_type; + using return_type = R; + using base_type = nsRunnableMethod<C, R, Owning, Kind>; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; @@ -822,22 +790,22 @@ template <typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As> struct nsRunnableMethodTraits<PtrType, R (__stdcall C::*)(As...), Owning, Kind> { - typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; + using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>; static_assert(std::is_base_of<C, class_type>::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod<C, R, Owning, Kind> base_type; + using return_type = R; + using base_type = nsRunnableMethod<C, R, Owning, Kind>; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; template <typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind> struct nsRunnableMethodTraits<PtrType, R (NS_STDCALL C::*)(), Owning, Kind> { - typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type; + using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>; static_assert(std::is_base_of<C, class_type>::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod<C, R, Owning, Kind> base_type; + using return_type = R; + using base_type = nsRunnableMethod<C, R, Owning, Kind>; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; @@ -845,12 +813,11 @@ template <typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind, typename... As> struct nsRunnableMethodTraits<PtrType, R (__stdcall C::*)(As...) const, Owning, Kind> { - typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type - class_type; + using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>; static_assert(std::is_base_of<C, class_type>::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod<C, R, Owning, Kind> base_type; + using return_type = R; + using base_type = nsRunnableMethod<C, R, Owning, Kind>; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; @@ -858,12 +825,11 @@ template <typename PtrType, class C, typename R, bool Owning, mozilla::RunnableKind Kind> struct nsRunnableMethodTraits<PtrType, R (NS_STDCALL C::*)() const, Owning, Kind> { - typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type - class_type; + using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>; static_assert(std::is_base_of<C, class_type>::value, "Stored class must inherit from method's class"); - typedef R return_type; - typedef nsRunnableMethod<C, R, Owning, Kind> base_type; + using return_type = R; + using base_type = nsRunnableMethod<C, R, Owning, Kind>; static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable; }; # endif @@ -881,19 +847,6 @@ struct IsParameterStorageClass : public std::false_type {}; // store arguments, and how to pass them to the target method. template <typename T> -struct StoreCopyPassByValue { - using stored_type = std::decay_t<T>; - typedef stored_type passed_type; - stored_type m; - template <typename A> - MOZ_IMPLICIT StoreCopyPassByValue(A&& a) : m(std::forward<A>(a)) {} - passed_type PassAsParameter() { return m; } -}; -template <typename S> -struct IsParameterStorageClass<StoreCopyPassByValue<S>> - : public std::true_type {}; - -template <typename T> struct StoreCopyPassByConstLRef { using stored_type = std::decay_t<T>; typedef const stored_type& passed_type; @@ -907,19 +860,6 @@ struct IsParameterStorageClass<StoreCopyPassByConstLRef<S>> : public std::true_type {}; template <typename T> -struct StoreCopyPassByLRef { - using stored_type = std::decay_t<T>; - typedef stored_type& passed_type; - stored_type m; - template <typename A> - MOZ_IMPLICIT StoreCopyPassByLRef(A&& a) : m(std::forward<A>(a)) {} - passed_type PassAsParameter() { return m; } -}; -template <typename S> -struct IsParameterStorageClass<StoreCopyPassByLRef<S>> : public std::true_type { -}; - -template <typename T> struct StoreCopyPassByRRef { using stored_type = std::decay_t<T>; typedef stored_type&& passed_type; @@ -996,32 +936,6 @@ template <typename S> struct IsParameterStorageClass<StoreConstPtrPassByConstPtr<S>> : public std::true_type {}; -template <typename T> -struct StoreCopyPassByConstPtr { - typedef T stored_type; - typedef const T* passed_type; - stored_type m; - template <typename A> - MOZ_IMPLICIT StoreCopyPassByConstPtr(A&& a) : m(std::forward<A>(a)) {} - passed_type PassAsParameter() { return &m; } -}; -template <typename S> -struct IsParameterStorageClass<StoreCopyPassByConstPtr<S>> - : public std::true_type {}; - -template <typename T> -struct StoreCopyPassByPtr { - typedef T stored_type; - typedef T* passed_type; - stored_type m; - template <typename A> - MOZ_IMPLICIT StoreCopyPassByPtr(A&& a) : m(std::forward<A>(a)) {} - passed_type PassAsParameter() { return &m; } -}; -template <typename S> -struct IsParameterStorageClass<StoreCopyPassByPtr<S>> : public std::true_type { -}; - namespace detail { template <typename> @@ -1035,94 +949,101 @@ template <class> static auto HasRefCountMethodsTest(long) -> std::false_type; template <class T> -struct HasRefCountMethods : decltype(HasRefCountMethodsTest<T>(0)) {}; - -template <typename TWithoutPointer> -struct NonnsISupportsPointerStorageClass - : std::conditional< - std::is_const_v<TWithoutPointer>, - StoreConstPtrPassByConstPtr<std::remove_const_t<TWithoutPointer>>, - StorePtrPassByPtr<TWithoutPointer>> { - using Type = typename NonnsISupportsPointerStorageClass::conditional::type; +constexpr static bool HasRefCountMethods = + decltype(HasRefCountMethodsTest<T>(0))::value; + +// Choose storage&passing strategy based on preferred storage type: +// - If IsParameterStorageClass<T>::value is true, use as-is. +// - RC* -> StoreRefPtrPassByPtr<RC> :Store RefPtr<RC>, pass RC* +// ^^ RC quacks like a ref-counted type (i.e., has AddRef and Release methods) +// - const T* -> StoreConstPtrPassByConstPtr<T> :Store const T*, pass const T* +// - T* -> StorePtrPassByPtr<T> :Store T*, pass T*. +// - const T& -> StoreConstRefPassByConstLRef<T>:Store const T&, pass const T&. +// - T& -> StoreRefPassByLRef<T> :Store T&, pass T&. +// - T&& -> StoreCopyPassByRRef<T> :Store T, pass std::move(T). +// - RefPtr<T>, nsCOMPtr<T> +// -> StoreRefPtrPassByPtr<T> :Store RefPtr<T>, pass T* +// - Other T -> StoreCopyPassByConstLRef<T> :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 <typename T> +struct OtherParameterStorage; + +// The `IsParameterStorageClass` and `RC*` cases must be handled separately (see +// `ParameterStorageHelper`, below) until we can use C++20 concepts. + +template <typename T> +struct OtherParameterStorage<const T*> { + using Type = StoreConstPtrPassByConstPtr<T>; }; -template <typename TWithoutPointer> -struct PointerStorageClass - : std::conditional< - HasRefCountMethods<TWithoutPointer>::value, - StoreRefPtrPassByPtr<TWithoutPointer>, - typename NonnsISupportsPointerStorageClass<TWithoutPointer>::Type> { - using Type = typename PointerStorageClass::conditional::type; +template <typename T> +struct OtherParameterStorage<T*> { + using Type = StorePtrPassByPtr<T>; }; -template <typename TWithoutRef> -struct LValueReferenceStorageClass - : std::conditional< - std::is_const_v<TWithoutRef>, - StoreConstRefPassByConstLRef<std::remove_const_t<TWithoutRef>>, - StoreRefPassByLRef<TWithoutRef>> { - using Type = typename LValueReferenceStorageClass::conditional::type; +template <typename T> +struct OtherParameterStorage<const T&> { + using Type = StoreConstRefPassByConstLRef<T>; }; template <typename T> -struct SmartPointerStorageClass - : std::conditional< - mozilla::IsRefcountedSmartPointer<T>::value, - StoreRefPtrPassByPtr<typename mozilla::RemoveSmartPointer<T>::Type>, - StoreCopyPassByConstLRef<T>> { - using Type = typename SmartPointerStorageClass::conditional::type; +struct OtherParameterStorage<T&> { + using Type = StoreRefPassByLRef<T>; }; template <typename T> -struct NonLValueReferenceStorageClass - : std::conditional<std::is_rvalue_reference_v<T>, - StoreCopyPassByRRef<std::remove_reference_t<T>>, - typename SmartPointerStorageClass<T>::Type> { - using Type = typename NonLValueReferenceStorageClass::conditional::type; +struct OtherParameterStorage<RefPtr<T>> { + using Type = StoreRefPtrPassByPtr<T>; }; template <typename T> -struct NonPointerStorageClass - : std::conditional<std::is_lvalue_reference_v<T>, - typename LValueReferenceStorageClass< - std::remove_reference_t<T>>::Type, - typename NonLValueReferenceStorageClass<T>::Type> { - using Type = typename NonPointerStorageClass::conditional::type; +struct OtherParameterStorage<nsCOMPtr<T>> { + using Type = StoreRefPtrPassByPtr<T>; }; template <typename T> -struct NonParameterStorageClass - : std::conditional< - std::is_pointer_v<T>, - typename PointerStorageClass<std::remove_pointer_t<T>>::Type, - typename NonPointerStorageClass<T>::Type> { - using Type = typename NonParameterStorageClass::conditional::type; +struct OtherParameterStorage<T&&> { + using Type = StoreCopyPassByRRef<T>; +}; + +template <typename T> +struct OtherParameterStorage<const T&&> { + // This is good advice regardless of the types you're handling. + static_assert(!SFINAE1True<T>::value, "please use a lambda function"); +}; + +// default impl. +template <typename T> +struct OtherParameterStorage { + using Type = StoreCopyPassByConstLRef<T>; +}; + +template <typename T, bool A = IsParameterStorageClass<T>::value, + bool B = std::is_pointer_v<T> && + HasRefCountMethods<std::remove_pointer_t<T>>> +struct ParameterStorageHelper; + +template <typename T, bool B> +struct ParameterStorageHelper<T, true, B> { + using Type = T; +}; + +template <typename T> +struct ParameterStorageHelper<T, false, true> { + using Type = StoreRefPtrPassByPtr<std::remove_pointer_t<T>>; +}; + +template <typename T> +struct ParameterStorageHelper<T, false, false> { + using Type = typename OtherParameterStorage<std::remove_cv_t<T>>::Type; }; -// Choose storage&passing strategy based on preferred storage type: -// - If IsParameterStorageClass<T>::value is true, use as-is. -// - RC* -> StoreRefPtrPassByPtr<RC> :Store RefPtr<RC>, pass RC* -// ^^ RC quacks like a ref-counted type (i.e., has AddRef and Release methods) -// - const T* -> StoreConstPtrPassByConstPtr<T> :Store const T*, pass const T* -// - T* -> StorePtrPassByPtr<T> :Store T*, pass T*. -// - const T& -> StoreConstRefPassByConstLRef<T>:Store const T&, pass const T&. -// - T& -> StoreRefPassByLRef<T> :Store T&, pass T&. -// - T&& -> StoreCopyPassByRRef<T> :Store T, pass std::move(T). -// - RefPtr<T>, nsCOMPtr<T> -// -> StoreRefPtrPassByPtr<T> :Store RefPtr<T>, pass T* -// - Other T -> StoreCopyPassByConstLRef<T> :Store T, pass const T&. -// Other available explicit options: -// - StoreCopyPassByValue<T> :Store T, pass T. -// - StoreCopyPassByLRef<T> :Store T, pass T& (of copy!) -// - StoreCopyPassByConstPtr<T> :Store T, pass const T* -// - StoreCopyPassByPtr<T> :Store T, pass T* (of copy!) -// Or create your own class with PassAsParameter() method, optional -// clean-up in destructor, and with associated IsParameterStorageClass<>. template <typename T> -struct ParameterStorage - : std::conditional<IsParameterStorageClass<T>::value, T, - typename NonParameterStorageClass<T>::Type> { - using Type = typename ParameterStorage::conditional::type; +struct ParameterStorage { + using Type = typename ParameterStorageHelper<T>::Type; }; template <class T> |