summaryrefslogtreecommitdiffstats
path: root/xpcom/threads
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:13:27 +0000
commit40a355a42d4a9444dc753c04c6608dade2f06a23 (patch)
tree871fc667d2de662f171103ce5ec067014ef85e61 /xpcom/threads
parentAdding upstream version 124.0.1. (diff)
downloadfirefox-upstream/125.0.1.tar.xz
firefox-upstream/125.0.1.zip
Adding upstream version 125.0.1.upstream/125.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xpcom/threads')
-rw-r--r--xpcom/threads/MozPromise.h200
-rw-r--r--xpcom/threads/Mutex.h4
-rw-r--r--xpcom/threads/nsThreadManager.cpp6
-rw-r--r--xpcom/threads/nsThreadUtils.h301
4 files changed, 201 insertions, 310 deletions
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<std::remove_reference_t<T>> {};
} // namespace detail
-template <typename MethodType>
-using TakesArgument =
- std::integral_constant<bool, detail::MethodTrait<MethodType>::ArgSize != 0>;
+template <typename T>
+using MethodReturnType = typename detail::MethodTrait<T>::ReturnType;
-template <typename MethodType, typename TargetType>
-using ReturnTypeIs =
- std::is_convertible<typename detail::MethodTrait<MethodType>::ReturnType,
- TargetType>;
+template <typename MethodType>
+constexpr bool TakesAnyArguments =
+ detail::MethodTrait<MethodType>::ArgSize != 0;
template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
class MozPromise;
-template <typename Return>
-struct IsMozPromise : std::false_type {};
+template <typename T>
+constexpr bool IsMozPromise = false;
template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
-struct IsMozPromise<MozPromise<ResolveValueT, RejectValueT, IsExclusive>>
- : std::true_type {};
+constexpr bool
+ IsMozPromise<MozPromise<ResolveValueT, RejectValueT, IsExclusive>> = 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 <typename ResolveValueType_>
@@ -288,12 +286,10 @@ class MozPromise : public MozPromiseBase {
return p;
}
- typedef MozPromise<CopyableTArray<ResolveValueType>, RejectValueType,
- IsExclusive>
- AllPromiseType;
-
- typedef MozPromise<CopyableTArray<ResolveOrRejectValue>, bool, IsExclusive>
- AllSettledPromiseType;
+ using AllPromiseType = MozPromise<CopyableTArray<ResolveValueType>,
+ RejectValueType, IsExclusive>;
+ using AllSettledPromiseType =
+ MozPromise<CopyableTArray<ResolveOrRejectValue>, 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<IsExclusive, ResolveOrRejectValue&&,
- const ResolveOrRejectValue&>
- ResolveOrRejectValueParam;
+ using ResolveOrRejectValueParam =
+ std::conditional_t<IsExclusive, ResolveOrRejectValue&&,
+ const ResolveOrRejectValue&>;
- typedef std::conditional_t<IsExclusive, ResolveValueType&&,
- const ResolveValueType&>
- ResolveValueTypeParam;
+ using ResolveValueTypeParam =
+ std::conditional_t<IsExclusive, ResolveValueType&&,
+ const ResolveValueType&>;
- typedef std::conditional_t<IsExclusive, RejectValueType&&,
- const RejectValueType&>
- RejectValueTypeParam;
+ using RejectValueTypeParam =
+ std::conditional_t<IsExclusive, RejectValueType&&,
+ const RejectValueType&>;
class AllSettledPromiseHolder : public MozPromiseRefcountable {
public:
@@ -648,15 +644,15 @@ class MozPromise : public MozPromiseBase {
* make the resolve/reject value argument "optional".
*/
template <typename ThisType, typename MethodType, typename ValueType>
- static std::enable_if_t<TakesArgument<MethodType>::value,
- typename detail::MethodTrait<MethodType>::ReturnType>
+ static std::enable_if_t<TakesAnyArguments<MethodType>,
+ MethodReturnType<MethodType>>
InvokeMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue) {
return (aThisVal->*aMethod)(std::forward<ValueType>(aValue));
}
template <typename ThisType, typename MethodType, typename ValueType>
- static std::enable_if_t<!TakesArgument<MethodType>::value,
- typename detail::MethodTrait<MethodType>::ReturnType>
+ static std::enable_if_t<!TakesAnyArguments<MethodType>,
+ MethodReturnType<MethodType>>
InvokeMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue) {
return (aThisVal->*aMethod)();
}
@@ -697,18 +693,14 @@ class MozPromise : public MozPromiseBase {
: public ThenValueBase {
friend class ThenCommand<ThenValue>;
- using R1 = typename RemoveSmartPointer<
- typename detail::MethodTrait<ResolveMethodType>::ReturnType>::Type;
- using R2 = typename RemoveSmartPointer<
- typename detail::MethodTrait<RejectMethodType>::ReturnType>::Type;
- using SupportChaining =
- std::integral_constant<bool, IsMozPromise<R1>::value &&
- std::is_same_v<R1, R2>>;
+ using R1 = RemoveSmartPointer<MethodReturnType<ResolveMethodType>>;
+ using R2 = RemoveSmartPointer<MethodReturnType<RejectMethodType>>;
+ constexpr static bool SupportChaining =
+ IsMozPromise<R1> && std::is_same_v<R1, R2>;
// Fall back to MozPromise when promise chaining is not supported to make
// code compile.
- using PromiseType =
- std::conditional_t<SupportChaining::value, R1, MozPromise>;
+ using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
public:
ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
@@ -736,13 +728,13 @@ class MozPromise : public MozPromiseBase {
void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
if (aValue.IsResolve()) {
- InvokeCallbackMethod<SupportChaining::value>(
- mThisVal.get(), mResolveMethod, MaybeMove(aValue.ResolveValue()),
- std::move(mCompletionPromise));
+ InvokeCallbackMethod<SupportChaining>(mThisVal.get(), mResolveMethod,
+ MaybeMove(aValue.ResolveValue()),
+ std::move(mCompletionPromise));
} else {
- InvokeCallbackMethod<SupportChaining::value>(
- mThisVal.get(), mRejectMethod, MaybeMove(aValue.RejectValue()),
- std::move(mCompletionPromise));
+ InvokeCallbackMethod<SupportChaining>(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<ThisType*, ResolveRejectMethodType> : public ThenValueBase {
friend class ThenCommand<ThenValue>;
- using R1 = typename RemoveSmartPointer<typename detail::MethodTrait<
- ResolveRejectMethodType>::ReturnType>::Type;
- using SupportChaining =
- std::integral_constant<bool, IsMozPromise<R1>::value>;
+ using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectMethodType>>;
+ constexpr static bool SupportChaining = IsMozPromise<R1>;
// Fall back to MozPromise when promise chaining is not supported to make
// code compile.
- using PromiseType =
- std::conditional_t<SupportChaining::value, R1, MozPromise>;
+ using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
public:
ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
@@ -798,7 +787,7 @@ class MozPromise : public MozPromiseBase {
}
void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
- InvokeCallbackMethod<SupportChaining::value>(
+ InvokeCallbackMethod<SupportChaining>(
mThisVal.get(), mResolveRejectMethod, MaybeMove(aValue),
std::move(mCompletionPromise));
@@ -822,18 +811,14 @@ class MozPromise : public MozPromiseBase {
class ThenValue<ResolveFunction, RejectFunction> : public ThenValueBase {
friend class ThenCommand<ThenValue>;
- using R1 = typename RemoveSmartPointer<
- typename detail::MethodTrait<ResolveFunction>::ReturnType>::Type;
- using R2 = typename RemoveSmartPointer<
- typename detail::MethodTrait<RejectFunction>::ReturnType>::Type;
- using SupportChaining =
- std::integral_constant<bool, IsMozPromise<R1>::value &&
- std::is_same_v<R1, R2>>;
+ using R1 = RemoveSmartPointer<MethodReturnType<ResolveFunction>>;
+ using R2 = RemoveSmartPointer<MethodReturnType<RejectFunction>>;
+ constexpr static bool SupportChaining =
+ IsMozPromise<R1> && std::is_same_v<R1, R2>;
// Fall back to MozPromise when promise chaining is not supported to make
// code compile.
- using PromiseType =
- std::conditional_t<SupportChaining::value, R1, MozPromise>;
+ using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
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<SupportChaining::value>(
+ InvokeCallbackMethod<SupportChaining>(
mResolveFunction.ptr(), &ResolveFunction::operator(),
MaybeMove(aValue.ResolveValue()), std::move(mCompletionPromise));
} else {
- InvokeCallbackMethod<SupportChaining::value>(
+ InvokeCallbackMethod<SupportChaining>(
mRejectFunction.ptr(), &RejectFunction::operator(),
MaybeMove(aValue.RejectValue()), std::move(mCompletionPromise));
}
@@ -896,15 +881,12 @@ class MozPromise : public MozPromiseBase {
class ThenValue<ResolveRejectFunction> : public ThenValueBase {
friend class ThenCommand<ThenValue>;
- using R1 = typename RemoveSmartPointer<
- typename detail::MethodTrait<ResolveRejectFunction>::ReturnType>::Type;
- using SupportChaining =
- std::integral_constant<bool, IsMozPromise<R1>::value>;
+ using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectFunction>>;
+ constexpr static bool SupportChaining = IsMozPromise<R1>;
// Fall back to MozPromise when promise chaining is not supported to make
// code compile.
- using PromiseType =
- std::conditional_t<SupportChaining::value, R1, MozPromise>;
+ using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
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<SupportChaining::value>(
+ InvokeCallbackMethod<SupportChaining>(
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<PromiseType>() {
static_assert(
- ThenValueType::SupportChaining::value,
+ ThenValueType::SupportChaining,
"The resolve/reject callback needs to return a RefPtr<MozPromise> "
"in order to do promise chaining.");
@@ -1336,12 +1318,18 @@ class MozPromise<ResolveValueT, RejectValueT, IsExclusive>::Private
};
// A generic promise type that does the trick for simple use cases.
-typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> 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<bool, nsresult, /* IsExclusive = */ true>;
// A generic, non-exclusive promise type that does the trick for simple use
// cases.
-typedef MozPromise<bool, nsresult, /* IsExclusive = */ false>
- GenericNonExclusivePromise;
+//
+// Vaguely deprecated, as above.
+using GenericNonExclusivePromise =
+ MozPromise<bool, nsresult, /* IsExclusive = */ false>;
/*
* 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<FunctionStorage> 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 <typename T>
+constexpr static bool IsRefPtrMozPromise = false;
+template <typename T, typename U, bool B>
+constexpr static bool IsRefPtrMozPromise<RefPtr<MozPromise<T, U, B>>> = 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 <typename Function>
static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName,
- AllowInvokeAsyncFunctionLVRef, Function&& aFunction)
- -> decltype(aFunction()) {
- static_assert(
- IsRefcountedSmartPointer<decltype(aFunction())>::value &&
- IsMozPromise<
- typename RemoveSmartPointer<decltype(aFunction())>::Type>::value,
- "Function object must return RefPtr<MozPromise>");
+ Function&& aFunction) -> decltype(aFunction()) {
+ static_assert(!std::is_lvalue_reference_v<Function>,
+ "Function object must not be passed by lvalue-ref (to avoid "
+ "unplanned copies); Consider move()ing the object.");
+
+ static_assert(detail::IsRefPtrMozPromise<decltype(aFunction())>,
+ "Function object must return RefPtr<MozPromise>");
MOZ_ASSERT(aTarget);
- typedef typename RemoveSmartPointer<decltype(aFunction())>::Type PromiseType;
+ typedef RemoveSmartPointer<decltype(aFunction())> PromiseType;
typedef detail::ProxyFunctionRunnable<Function, PromiseType>
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 <typename Function>
-static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName,
- Function&& aFunction) -> decltype(aFunction()) {
- static_assert(!std::is_lvalue_reference_v<Function>,
- "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<Function>(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 <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>