forked from mirrors/gecko-dev
Backed out 6 changesets (bug 1880192) for causing build bustages on MozPromise.h. CLOSED TREE
Backed out changeset b73f06a9fdb1 (bug 1880192) Backed out changeset ee04f994bad8 (bug 1880192) Backed out changeset 8c7a686c8691 (bug 1880192) Backed out changeset 15e93c260557 (bug 1880192) Backed out changeset b5f62ac62087 (bug 1880192) Backed out changeset ff2d8eae2a68 (bug 1880192)
This commit is contained in:
parent
8cc44430a4
commit
0783fb05a1
9 changed files with 602 additions and 289 deletions
|
|
@ -318,7 +318,7 @@ struct AudioChunk {
|
|||
* A list of audio samples consisting of a sequence of slices of SharedBuffers.
|
||||
* The audio rate is determined by the track, not stored in this class.
|
||||
*/
|
||||
class AudioSegment final : public MediaSegmentBase<AudioSegment, AudioChunk> {
|
||||
class AudioSegment : public MediaSegmentBase<AudioSegment, AudioChunk> {
|
||||
// The channel count that MaxChannelCount() returned last time it was called.
|
||||
uint32_t mMemoizedMaxChannelCount = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -109,8 +109,8 @@ class VideoFrameConverter {
|
|||
// for processing so it can be immediately sent.
|
||||
mLastFrameQueuedForProcessing.mTime = time;
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
mTaskQueue->Dispatch(NewRunnableMethod<FrameToProcess>(
|
||||
MOZ_ALWAYS_SUCCEEDS(mTaskQueue->Dispatch(
|
||||
NewRunnableMethod<StoreCopyPassByLRef<FrameToProcess>>(
|
||||
"VideoFrameConverter::ProcessVideoFrame", this,
|
||||
&VideoFrameConverter::ProcessVideoFrame,
|
||||
mLastFrameQueuedForProcessing)));
|
||||
|
|
@ -138,8 +138,8 @@ class VideoFrameConverter {
|
|||
mLastFrameQueuedForProcessing.mForceBlack = true;
|
||||
mLastFrameQueuedForProcessing.mImage = nullptr;
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
mTaskQueue->Dispatch(NewRunnableMethod<FrameToProcess>(
|
||||
MOZ_ALWAYS_SUCCEEDS(mTaskQueue->Dispatch(
|
||||
NewRunnableMethod<StoreCopyPassByLRef<FrameToProcess>>(
|
||||
"VideoFrameConverter::ProcessVideoFrame", this,
|
||||
&VideoFrameConverter::ProcessVideoFrame,
|
||||
mLastFrameQueuedForProcessing)));
|
||||
|
|
@ -293,10 +293,11 @@ class VideoFrameConverter {
|
|||
return;
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(mTaskQueue->Dispatch(NewRunnableMethod<FrameToProcess>(
|
||||
"VideoFrameConverter::ProcessVideoFrame", this,
|
||||
&VideoFrameConverter::ProcessVideoFrame,
|
||||
mLastFrameQueuedForProcessing)));
|
||||
MOZ_ALWAYS_SUCCEEDS(mTaskQueue->Dispatch(
|
||||
NewRunnableMethod<StoreCopyPassByLRef<FrameToProcess>>(
|
||||
"VideoFrameConverter::ProcessVideoFrame", this,
|
||||
&VideoFrameConverter::ProcessVideoFrame,
|
||||
mLastFrameQueuedForProcessing)));
|
||||
}
|
||||
|
||||
void ProcessVideoFrame(const FrameToProcess& aFrame) {
|
||||
|
|
|
|||
|
|
@ -437,13 +437,12 @@ uint32_t SpeechRecognition::ProcessAudioSegment(AudioSegment* aSegment,
|
|||
// we need to call the nsISpeechRecognitionService::ProcessAudioSegment
|
||||
// in a separate thread so that any eventual encoding or pre-processing
|
||||
// of the audio does not block the main thread
|
||||
nsresult rv = mEncodeTaskQueue->Dispatch(NS_NewRunnableFunction(
|
||||
"nsISpeechRecognitionService::ProcessAudioSegment",
|
||||
[=, service = mRecognitionService,
|
||||
segment = std::move(*aSegment)]() mutable {
|
||||
service->ProcessAudioSegment(&segment, aTrackRate);
|
||||
}));
|
||||
|
||||
nsresult rv = mEncodeTaskQueue->Dispatch(
|
||||
NewRunnableMethod<StoreCopyPassByPtr<AudioSegment>, TrackRate>(
|
||||
"nsISpeechRecognitionService::ProcessAudioSegment",
|
||||
mRecognitionService,
|
||||
&nsISpeechRecognitionService::ProcessAudioSegment,
|
||||
std::move(*aSegment), aTrackRate));
|
||||
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
|
||||
Unused << rv;
|
||||
return samples;
|
||||
|
|
|
|||
|
|
@ -394,7 +394,8 @@ void APZCTreeManager::SetAllowedTouchBehavior(
|
|||
uint64_t aInputBlockId, const nsTArray<TouchBehaviorFlags>& aValues) {
|
||||
if (!APZThreadUtils::IsControllerThread()) {
|
||||
APZThreadUtils::RunOnControllerThread(
|
||||
NewRunnableMethod<uint64_t, nsTArray<TouchBehaviorFlags>>(
|
||||
NewRunnableMethod<uint64_t,
|
||||
StoreCopyPassByLRef<nsTArray<TouchBehaviorFlags>>>(
|
||||
"layers::APZCTreeManager::SetAllowedTouchBehavior", this,
|
||||
&APZCTreeManager::SetAllowedTouchBehavior, aInputBlockId,
|
||||
aValues.Clone()));
|
||||
|
|
|
|||
|
|
@ -364,13 +364,13 @@ nsresult nsWifiMonitor::DoScan() {
|
|||
}
|
||||
|
||||
return NS_DispatchToMainThread(
|
||||
NewRunnableMethod<nsTArray<RefPtr<nsIWifiAccessPoint>>, bool>(
|
||||
NewRunnableMethod<const nsTArray<RefPtr<nsIWifiAccessPoint>>&&, bool>(
|
||||
"CallWifiListeners", this, &nsWifiMonitor::CallWifiListeners,
|
||||
mLastAccessPoints.Clone(), accessPointsChanged));
|
||||
}
|
||||
|
||||
nsresult nsWifiMonitor::CallWifiListeners(
|
||||
const nsTArray<RefPtr<nsIWifiAccessPoint>>& aAccessPoints,
|
||||
nsTArray<RefPtr<nsIWifiAccessPoint>>&& aAccessPoints,
|
||||
bool aAccessPointsChanged) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
LOG(("Sending wifi access points to the listeners"));
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class nsWifiMonitor final : public nsIWifiMonitor, public nsIObserver {
|
|||
nsresult DoScan();
|
||||
|
||||
nsresult CallWifiListeners(
|
||||
const nsTArray<RefPtr<nsIWifiAccessPoint>>& aAccessPoints,
|
||||
nsTArray<RefPtr<nsIWifiAccessPoint>>&& aAccessPoints,
|
||||
bool aAccessPointsChanged);
|
||||
|
||||
nsresult PassErrorToWifiListeners(nsresult rv);
|
||||
|
|
|
|||
|
|
@ -885,88 +885,122 @@ TEST(ThreadUtils, IdleTaskRunner)
|
|||
|
||||
TEST(ThreadUtils, TypeTraits)
|
||||
{
|
||||
static_assert(std::is_same_v<int, mozilla::RemoveSmartPointer<int>>,
|
||||
"RemoveSmartPointer<int> should be int");
|
||||
static_assert(std::is_same_v<int*, mozilla::RemoveSmartPointer<int*>>,
|
||||
"RemoveSmartPointer<int*> should be int*");
|
||||
static_assert(std::is_same_v<UniquePtr<int>,
|
||||
mozilla::RemoveSmartPointer<UniquePtr<int>>>,
|
||||
"RemoveSmartPointer<UniquePtr<int>> should be UniquePtr<int>");
|
||||
static_assert(std::is_same_v<int, mozilla::RemoveSmartPointer<RefPtr<int>>>,
|
||||
"RemoveSmartPointer<RefPtr<int>> should be int");
|
||||
static_assert(!mozilla::IsRefcountedSmartPointer<int>::value,
|
||||
"IsRefcountedSmartPointer<int> should be false");
|
||||
static_assert(mozilla::IsRefcountedSmartPointer<RefPtr<int>>::value,
|
||||
"IsRefcountedSmartPointer<RefPtr<...>> should be true");
|
||||
static_assert(mozilla::IsRefcountedSmartPointer<const RefPtr<int>>::value,
|
||||
"IsRefcountedSmartPointer<const RefPtr<...>> should be true");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveSmartPointer<const RefPtr<int>>>,
|
||||
"RemoveSmartPointer<const RefPtr<int>> should be int");
|
||||
mozilla::IsRefcountedSmartPointer<volatile RefPtr<int>>::value,
|
||||
"IsRefcountedSmartPointer<volatile RefPtr<...>> should be true");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveSmartPointer<volatile RefPtr<int>>>,
|
||||
"RemoveSmartPointer<volatile RefPtr<int>> should be int");
|
||||
mozilla::IsRefcountedSmartPointer<const volatile RefPtr<int>>::value,
|
||||
"IsRefcountedSmartPointer<const volatile RefPtr<...>> should be true");
|
||||
static_assert(mozilla::IsRefcountedSmartPointer<nsCOMPtr<int>>::value,
|
||||
"IsRefcountedSmartPointer<nsCOMPtr<...>> should be true");
|
||||
static_assert(mozilla::IsRefcountedSmartPointer<const nsCOMPtr<int>>::value,
|
||||
"IsRefcountedSmartPointer<const nsCOMPtr<...>> should be true");
|
||||
static_assert(
|
||||
std::is_same_v<int,
|
||||
mozilla::RemoveSmartPointer<const volatile RefPtr<int>>>,
|
||||
"RemoveSmartPointer<const volatile RefPtr<int>> should be int");
|
||||
static_assert(std::is_same_v<int, mozilla::RemoveSmartPointer<nsCOMPtr<int>>>,
|
||||
"RemoveSmartPointer<nsCOMPtr<int>> should be int");
|
||||
mozilla::IsRefcountedSmartPointer<volatile nsCOMPtr<int>>::value,
|
||||
"IsRefcountedSmartPointer<volatile nsCOMPtr<...>> should be true");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveSmartPointer<const nsCOMPtr<int>>>,
|
||||
"RemoveSmartPointer<const nsCOMPtr<int>> should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveSmartPointer<volatile nsCOMPtr<int>>>,
|
||||
"RemoveSmartPointer<volatile nsCOMPtr<int>> should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int,
|
||||
mozilla::RemoveSmartPointer<const volatile nsCOMPtr<int>>>,
|
||||
"RemoveSmartPointer<const volatile nsCOMPtr<int>> should be int");
|
||||
mozilla::IsRefcountedSmartPointer<const volatile nsCOMPtr<int>>::value,
|
||||
"IsRefcountedSmartPointer<const volatile nsCOMPtr<...>> should be true");
|
||||
|
||||
static_assert(std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<int>>,
|
||||
"RemoveRawOrSmartPointer<int> should be int");
|
||||
static_assert(std::is_same_v<int, mozilla::RemoveSmartPointer<int>::Type>,
|
||||
"RemoveSmartPointer<int>::Type should be int");
|
||||
static_assert(std::is_same_v<int*, mozilla::RemoveSmartPointer<int*>::Type>,
|
||||
"RemoveSmartPointer<int*>::Type should be int*");
|
||||
static_assert(
|
||||
std::is_same_v<UniquePtr<int>,
|
||||
mozilla::RemoveRawOrSmartPointer<UniquePtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<UniquePtr<int>> should be UniquePtr<int>");
|
||||
static_assert(std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<int*>>,
|
||||
"RemoveRawOrSmartPointer<int*> should be int");
|
||||
mozilla::RemoveSmartPointer<UniquePtr<int>>::Type>,
|
||||
"RemoveSmartPointer<UniquePtr<int>>::Type should be UniquePtr<int>");
|
||||
static_assert(
|
||||
std::is_same_v<const int, mozilla::RemoveRawOrSmartPointer<const int*>>,
|
||||
"RemoveRawOrSmartPointer<const int*> should be const int");
|
||||
std::is_same_v<int, mozilla::RemoveSmartPointer<RefPtr<int>>::Type>,
|
||||
"RemoveSmartPointer<RefPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveSmartPointer<const RefPtr<int>>::Type>,
|
||||
"RemoveSmartPointer<const RefPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int,
|
||||
mozilla::RemoveSmartPointer<volatile RefPtr<int>>::Type>,
|
||||
"RemoveSmartPointer<volatile RefPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
int, mozilla::RemoveSmartPointer<const volatile RefPtr<int>>::Type>,
|
||||
"RemoveSmartPointer<const volatile RefPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveSmartPointer<nsCOMPtr<int>>::Type>,
|
||||
"RemoveSmartPointer<nsCOMPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int,
|
||||
mozilla::RemoveSmartPointer<const nsCOMPtr<int>>::Type>,
|
||||
"RemoveSmartPointer<const nsCOMPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int,
|
||||
mozilla::RemoveSmartPointer<volatile nsCOMPtr<int>>::Type>,
|
||||
"RemoveSmartPointer<volatile nsCOMPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
int, mozilla::RemoveSmartPointer<const volatile nsCOMPtr<int>>::Type>,
|
||||
"RemoveSmartPointer<const volatile nsCOMPtr<int>>::Type should be int");
|
||||
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<int>::Type>,
|
||||
"RemoveRawOrSmartPointer<int>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<UniquePtr<int>,
|
||||
mozilla::RemoveRawOrSmartPointer<UniquePtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<UniquePtr<int>>::Type should be UniquePtr<int>");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<int*>::Type>,
|
||||
"RemoveRawOrSmartPointer<int*>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<const int,
|
||||
mozilla::RemoveRawOrSmartPointer<const int*>::Type>,
|
||||
"RemoveRawOrSmartPointer<const int*>::Type should be const int");
|
||||
static_assert(
|
||||
std::is_same_v<volatile int,
|
||||
mozilla::RemoveRawOrSmartPointer<volatile int*>>,
|
||||
"RemoveRawOrSmartPointer<volatile int*> should be volatile int");
|
||||
mozilla::RemoveRawOrSmartPointer<volatile int*>::Type>,
|
||||
"RemoveRawOrSmartPointer<volatile int*>::Type should be volatile int");
|
||||
static_assert(
|
||||
std::is_same_v<const volatile int,
|
||||
mozilla::RemoveRawOrSmartPointer<const volatile int*>>,
|
||||
"RemoveRawOrSmartPointer<const volatile int*> should be const "
|
||||
std::is_same_v<const volatile int, mozilla::RemoveRawOrSmartPointer<
|
||||
const volatile int*>::Type>,
|
||||
"RemoveRawOrSmartPointer<const volatile int*>::Type should be const "
|
||||
"volatile int");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<RefPtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<RefPtr<int>> should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<const RefPtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<const RefPtr<int>> should be int");
|
||||
std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<RefPtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<RefPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int,
|
||||
mozilla::RemoveRawOrSmartPointer<volatile RefPtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<volatile RefPtr<int>> should be int");
|
||||
mozilla::RemoveRawOrSmartPointer<const RefPtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<const RefPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
int, mozilla::RemoveRawOrSmartPointer<const volatile RefPtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<const volatile RefPtr<int>> should be "
|
||||
int, mozilla::RemoveRawOrSmartPointer<volatile RefPtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<volatile RefPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<
|
||||
const volatile RefPtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<const volatile RefPtr<int>>::Type should be "
|
||||
"int");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<nsCOMPtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<nsCOMPtr<int>> should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int,
|
||||
mozilla::RemoveRawOrSmartPointer<const nsCOMPtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<const nsCOMPtr<int>> should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int,
|
||||
mozilla::RemoveRawOrSmartPointer<volatile nsCOMPtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<volatile nsCOMPtr<int>> should be int");
|
||||
mozilla::RemoveRawOrSmartPointer<nsCOMPtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<nsCOMPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
int, mozilla::RemoveRawOrSmartPointer<const volatile nsCOMPtr<int>>>,
|
||||
"RemoveRawOrSmartPointer<const volatile nsCOMPtr<int>> should be "
|
||||
int, mozilla::RemoveRawOrSmartPointer<const nsCOMPtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<const nsCOMPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
int, mozilla::RemoveRawOrSmartPointer<volatile nsCOMPtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<volatile nsCOMPtr<int>>::Type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<int, mozilla::RemoveRawOrSmartPointer<
|
||||
const volatile nsCOMPtr<int>>::Type>,
|
||||
"RemoveRawOrSmartPointer<const volatile nsCOMPtr<int>>::Type should be "
|
||||
"int");
|
||||
}
|
||||
|
||||
|
|
@ -1254,9 +1288,15 @@ TEST(ThreadUtils, main)
|
|||
|
||||
static_assert(!IsParameterStorageClass<int>::value,
|
||||
"'int' should not be recognized as Storage Class");
|
||||
static_assert(
|
||||
IsParameterStorageClass<StoreCopyPassByValue<int>>::value,
|
||||
"StoreCopyPassByValue<int> should be recognized as Storage Class");
|
||||
static_assert(
|
||||
IsParameterStorageClass<StoreCopyPassByConstLRef<int>>::value,
|
||||
"StoreCopyPassByConstLRef<int> should be recognized as Storage Class");
|
||||
static_assert(
|
||||
IsParameterStorageClass<StoreCopyPassByLRef<int>>::value,
|
||||
"StoreCopyPassByLRef<int> should be recognized as Storage Class");
|
||||
static_assert(
|
||||
IsParameterStorageClass<StoreCopyPassByRRef<int>>::value,
|
||||
"StoreCopyPassByRRef<int> should be recognized as Storage Class");
|
||||
|
|
@ -1275,6 +1315,12 @@ TEST(ThreadUtils, main)
|
|||
static_assert(
|
||||
IsParameterStorageClass<StoreConstPtrPassByConstPtr<int>>::value,
|
||||
"StoreConstPtrPassByConstPtr<int> should be recognized as Storage Class");
|
||||
static_assert(
|
||||
IsParameterStorageClass<StoreCopyPassByConstPtr<int>>::value,
|
||||
"StoreCopyPassByConstPtr<int> should be recognized as Storage Class");
|
||||
static_assert(
|
||||
IsParameterStorageClass<StoreCopyPassByPtr<int>>::value,
|
||||
"StoreCopyPassByPtr<int> should be recognized as Storage Class");
|
||||
|
||||
RefPtr<ThreadUtilsObject> rpt(new ThreadUtilsObject);
|
||||
int count = 0;
|
||||
|
|
@ -1313,6 +1359,11 @@ TEST(ThreadUtils, main)
|
|||
StoreCopyPassByConstLRef<int>>,
|
||||
"detail::ParameterStorage<int>::Type should be "
|
||||
"StoreCopyPassByConstLRef<int>");
|
||||
static_assert(std::is_same_v<
|
||||
::detail::ParameterStorage<StoreCopyPassByValue<int>>::Type,
|
||||
StoreCopyPassByValue<int>>,
|
||||
"detail::ParameterStorage<StoreCopyPassByValue<int>>::Type "
|
||||
"should be StoreCopyPassByValue<int>");
|
||||
|
||||
r1 = NewRunnableMethod<int>("TestThreadUtils::ThreadUtilsObject::Test1i", rpt,
|
||||
&ThreadUtilsObject::Test1i, 12);
|
||||
|
|
@ -1429,6 +1480,37 @@ TEST(ThreadUtils, main)
|
|||
EXPECT_EQ(i, rpt->mA0);
|
||||
}
|
||||
|
||||
// Raw pointer to copy.
|
||||
static_assert(std::is_same_v<StoreCopyPassByPtr<int>::stored_type, int>,
|
||||
"StoreCopyPassByPtr<int>::stored_type should be int");
|
||||
static_assert(std::is_same_v<StoreCopyPassByPtr<int>::passed_type, int*>,
|
||||
"StoreCopyPassByPtr<int>::passed_type should be int*");
|
||||
{
|
||||
int i = 1202;
|
||||
r1 = NewRunnableMethod<StoreCopyPassByPtr<int>>(
|
||||
"TestThreadUtils::ThreadUtilsObject::Test1pi", rpt,
|
||||
&ThreadUtilsObject::Test1pi, i);
|
||||
r1->Run();
|
||||
EXPECT_EQ(count += 2, rpt->mCount);
|
||||
EXPECT_EQ(i, rpt->mA0);
|
||||
}
|
||||
|
||||
// Raw pointer to const copy.
|
||||
static_assert(std::is_same_v<StoreCopyPassByConstPtr<int>::stored_type, int>,
|
||||
"StoreCopyPassByConstPtr<int>::stored_type should be int");
|
||||
static_assert(
|
||||
std::is_same_v<StoreCopyPassByConstPtr<int>::passed_type, const int*>,
|
||||
"StoreCopyPassByConstPtr<int>::passed_type should be const int*");
|
||||
{
|
||||
int i = 1203;
|
||||
r1 = NewRunnableMethod<StoreCopyPassByConstPtr<int>>(
|
||||
"TestThreadUtils::ThreadUtilsObject::Test1pci", rpt,
|
||||
&ThreadUtilsObject::Test1pci, i);
|
||||
r1->Run();
|
||||
EXPECT_EQ(count += 2, rpt->mCount);
|
||||
EXPECT_EQ(i, rpt->mA0);
|
||||
}
|
||||
|
||||
// nsRefPtr to pointer.
|
||||
static_assert(
|
||||
std::is_same_v<::detail::ParameterStorage<
|
||||
|
|
@ -1454,7 +1536,7 @@ TEST(ThreadUtils, main)
|
|||
// (more nsRefPtr tests below)
|
||||
|
||||
// nsRefPtr for ref-countable classes that do not derive from ISupports.
|
||||
static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedFinal>,
|
||||
static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedFinal>::value,
|
||||
"ThreadUtilsRefCountedFinal has AddRef() and Release()");
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
|
|
@ -1462,7 +1544,7 @@ TEST(ThreadUtils, main)
|
|||
StoreRefPtrPassByPtr<ThreadUtilsRefCountedFinal>>,
|
||||
"ParameterStorage<ThreadUtilsRefCountedFinal*>::Type should be "
|
||||
"StoreRefPtrPassByPtr<ThreadUtilsRefCountedFinal>");
|
||||
static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedBase>,
|
||||
static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedBase>::value,
|
||||
"ThreadUtilsRefCountedBase has AddRef() and Release()");
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
|
|
@ -1470,8 +1552,9 @@ TEST(ThreadUtils, main)
|
|||
StoreRefPtrPassByPtr<ThreadUtilsRefCountedBase>>,
|
||||
"ParameterStorage<ThreadUtilsRefCountedBase*>::Type should be "
|
||||
"StoreRefPtrPassByPtr<ThreadUtilsRefCountedBase>");
|
||||
static_assert(::detail::HasRefCountMethods<ThreadUtilsRefCountedDerived>,
|
||||
"ThreadUtilsRefCountedDerived has AddRef() and Release()");
|
||||
static_assert(
|
||||
::detail::HasRefCountMethods<ThreadUtilsRefCountedDerived>::value,
|
||||
"ThreadUtilsRefCountedDerived has AddRef() and Release()");
|
||||
static_assert(
|
||||
std::is_same_v<
|
||||
::detail::ParameterStorage<ThreadUtilsRefCountedDerived*>::Type,
|
||||
|
|
@ -1479,7 +1562,7 @@ TEST(ThreadUtils, main)
|
|||
"ParameterStorage<ThreadUtilsRefCountedDerived*>::Type should be "
|
||||
"StoreRefPtrPassByPtr<ThreadUtilsRefCountedDerived>");
|
||||
|
||||
static_assert(!::detail::HasRefCountMethods<ThreadUtilsNonRefCounted>,
|
||||
static_assert(!::detail::HasRefCountMethods<ThreadUtilsNonRefCounted>::value,
|
||||
"ThreadUtilsNonRefCounted doesn't have AddRef() and Release()");
|
||||
static_assert(!std::is_same_v<
|
||||
::detail::ParameterStorage<ThreadUtilsNonRefCounted*>::Type,
|
||||
|
|
@ -1653,6 +1736,126 @@ TEST(ThreadUtils, main)
|
|||
|
||||
// Verify copy/move assumptions.
|
||||
|
||||
Spy::ClearAll();
|
||||
if (gDebug) {
|
||||
printf("%d - Test: Store copy from lvalue, pass by value\n", __LINE__);
|
||||
}
|
||||
{ // Block around nsCOMPtr lifetime.
|
||||
nsCOMPtr<nsIRunnable> r2;
|
||||
{ // Block around Spy lifetime.
|
||||
if (gDebug) {
|
||||
printf("%d - Spy s(10)\n", __LINE__);
|
||||
}
|
||||
Spy s(10);
|
||||
EXPECT_EQ(1, gConstructions);
|
||||
EXPECT_EQ(1, gAlive);
|
||||
if (gDebug) {
|
||||
printf(
|
||||
"%d - r2 = "
|
||||
"NewRunnableMethod<StoreCopyPassByValue<Spy>>(&TestByValue, s)\n",
|
||||
__LINE__);
|
||||
}
|
||||
r2 = NewRunnableMethod<StoreCopyPassByValue<Spy>>(
|
||||
"TestThreadUtils::ThreadUtilsObject::TestByValue", rpt,
|
||||
&ThreadUtilsObject::TestByValue, s);
|
||||
EXPECT_EQ(2, gAlive);
|
||||
EXPECT_LE(1, gCopyConstructions); // At least 1 copy-construction.
|
||||
Spy::ClearActions();
|
||||
if (gDebug) {
|
||||
printf("%d - End block with Spy s(10)\n", __LINE__);
|
||||
}
|
||||
}
|
||||
EXPECT_EQ(1, gDestructions);
|
||||
EXPECT_EQ(1, gAlive);
|
||||
Spy::ClearActions();
|
||||
if (gDebug) {
|
||||
printf("%d - Run()\n", __LINE__);
|
||||
}
|
||||
r2->Run();
|
||||
EXPECT_LE(1, gCopyConstructions); // Another copy-construction in call.
|
||||
EXPECT_EQ(10, rpt->mSpy.mID);
|
||||
EXPECT_LE(1, gDestructions);
|
||||
EXPECT_EQ(1, gAlive);
|
||||
Spy::ClearActions();
|
||||
if (gDebug) {
|
||||
printf("%d - End block with r\n", __LINE__);
|
||||
}
|
||||
}
|
||||
if (gDebug) {
|
||||
printf("%d - After end block with r\n", __LINE__);
|
||||
}
|
||||
EXPECT_EQ(1, gDestructions);
|
||||
EXPECT_EQ(0, gAlive);
|
||||
|
||||
Spy::ClearAll();
|
||||
if (gDebug) {
|
||||
printf("%d - Test: Store copy from prvalue, pass by value\n", __LINE__);
|
||||
}
|
||||
{
|
||||
if (gDebug) {
|
||||
printf(
|
||||
"%d - r3 = "
|
||||
"NewRunnableMethod<StoreCopyPassByValue<Spy>>(&TestByValue, "
|
||||
"Spy(11))\n",
|
||||
__LINE__);
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> r3 = NewRunnableMethod<StoreCopyPassByValue<Spy>>(
|
||||
"TestThreadUtils::ThreadUtilsObject::TestByValue", rpt,
|
||||
&ThreadUtilsObject::TestByValue, Spy(11));
|
||||
EXPECT_EQ(1, gAlive);
|
||||
EXPECT_EQ(1, gConstructions);
|
||||
EXPECT_LE(1, gMoveConstructions);
|
||||
Spy::ClearActions();
|
||||
if (gDebug) {
|
||||
printf("%d - Run()\n", __LINE__);
|
||||
}
|
||||
r3->Run();
|
||||
EXPECT_LE(1, gCopyConstructions); // Another copy-construction in call.
|
||||
EXPECT_EQ(11, rpt->mSpy.mID);
|
||||
EXPECT_LE(1, gDestructions);
|
||||
EXPECT_EQ(1, gAlive);
|
||||
Spy::ClearActions();
|
||||
if (gDebug) {
|
||||
printf("%d - End block with r\n", __LINE__);
|
||||
}
|
||||
}
|
||||
if (gDebug) {
|
||||
printf("%d - After end block with r\n", __LINE__);
|
||||
}
|
||||
EXPECT_EQ(1, gDestructions);
|
||||
EXPECT_EQ(0, gAlive);
|
||||
|
||||
Spy::ClearAll();
|
||||
{ // Store copy from xvalue, pass by value.
|
||||
nsCOMPtr<nsIRunnable> r4;
|
||||
{
|
||||
Spy s(12);
|
||||
EXPECT_EQ(1, gConstructions);
|
||||
EXPECT_EQ(1, gAlive);
|
||||
Spy::ClearActions();
|
||||
r4 = NewRunnableMethod<StoreCopyPassByValue<Spy>>(
|
||||
"TestThreadUtils::ThreadUtilsObject::TestByValue", rpt,
|
||||
&ThreadUtilsObject::TestByValue, std::move(s));
|
||||
EXPECT_LE(1, gMoveConstructions);
|
||||
EXPECT_EQ(1, gAlive);
|
||||
EXPECT_EQ(1, gZombies);
|
||||
Spy::ClearActions();
|
||||
}
|
||||
EXPECT_EQ(1, gDestructions);
|
||||
EXPECT_EQ(1, gAlive);
|
||||
EXPECT_EQ(0, gZombies);
|
||||
Spy::ClearActions();
|
||||
r4->Run();
|
||||
EXPECT_LE(1, gCopyConstructions); // Another copy-construction in call.
|
||||
EXPECT_EQ(12, rpt->mSpy.mID);
|
||||
EXPECT_LE(1, gDestructions);
|
||||
EXPECT_EQ(1, gAlive);
|
||||
Spy::ClearActions();
|
||||
}
|
||||
EXPECT_EQ(1, gDestructions);
|
||||
EXPECT_EQ(0, gAlive);
|
||||
// Won't test xvalues anymore, prvalues are enough to verify all rvalues.
|
||||
|
||||
Spy::ClearAll();
|
||||
if (gDebug) {
|
||||
printf("%d - Test: Store copy from lvalue, pass by const lvalue ref\n",
|
||||
|
|
|
|||
|
|
@ -82,22 +82,24 @@ struct MethodTrait : MethodTraitsHelper<std::remove_reference_t<T>> {};
|
|||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
using MethodReturnType = typename detail::MethodTrait<T>::ReturnType;
|
||||
|
||||
template <typename MethodType>
|
||||
constexpr bool TakesAnyArguments =
|
||||
detail::MethodTrait<MethodType>::ArgSize != 0;
|
||||
using TakesArgument =
|
||||
std::integral_constant<bool, detail::MethodTrait<MethodType>::ArgSize != 0>;
|
||||
|
||||
template <typename MethodType, typename TargetType>
|
||||
using ReturnTypeIs =
|
||||
std::is_convertible<typename detail::MethodTrait<MethodType>::ReturnType,
|
||||
TargetType>;
|
||||
|
||||
template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
|
||||
class MozPromise;
|
||||
|
||||
template <typename T>
|
||||
constexpr bool IsMozPromise = false;
|
||||
template <typename Return>
|
||||
struct IsMozPromise : std::false_type {};
|
||||
|
||||
template <typename ResolveValueT, typename RejectValueT, bool IsExclusive>
|
||||
constexpr bool
|
||||
IsMozPromise<MozPromise<ResolveValueT, RejectValueT, IsExclusive>> = true;
|
||||
struct IsMozPromise<MozPromise<ResolveValueT, RejectValueT, IsExclusive>>
|
||||
: std::true_type {};
|
||||
|
||||
/*
|
||||
* A promise manages an asynchronous request that may or may not be able to be
|
||||
|
|
@ -174,8 +176,8 @@ class MozPromise : public MozPromiseBase {
|
|||
}
|
||||
|
||||
public:
|
||||
using ResolveValueType = ResolveValueT;
|
||||
using RejectValueType = RejectValueT;
|
||||
typedef ResolveValueT ResolveValueType;
|
||||
typedef RejectValueT RejectValueType;
|
||||
class ResolveOrRejectValue {
|
||||
public:
|
||||
template <typename ResolveValueType_>
|
||||
|
|
@ -286,10 +288,12 @@ class MozPromise : public MozPromiseBase {
|
|||
return p;
|
||||
}
|
||||
|
||||
using AllPromiseType = MozPromise<CopyableTArray<ResolveValueType>,
|
||||
RejectValueType, IsExclusive>;
|
||||
using AllSettledPromiseType =
|
||||
MozPromise<CopyableTArray<ResolveOrRejectValue>, bool, IsExclusive>;
|
||||
typedef MozPromise<CopyableTArray<ResolveValueType>, RejectValueType,
|
||||
IsExclusive>
|
||||
AllPromiseType;
|
||||
|
||||
typedef MozPromise<CopyableTArray<ResolveOrRejectValue>, bool, IsExclusive>
|
||||
AllSettledPromiseType;
|
||||
|
||||
private:
|
||||
class AllPromiseHolder : public MozPromiseRefcountable {
|
||||
|
|
@ -346,17 +350,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.
|
||||
using ResolveOrRejectValueParam =
|
||||
std::conditional_t<IsExclusive, ResolveOrRejectValue&&,
|
||||
const ResolveOrRejectValue&>;
|
||||
typedef std::conditional_t<IsExclusive, ResolveOrRejectValue&&,
|
||||
const ResolveOrRejectValue&>
|
||||
ResolveOrRejectValueParam;
|
||||
|
||||
using ResolveValueTypeParam =
|
||||
std::conditional_t<IsExclusive, ResolveValueType&&,
|
||||
const ResolveValueType&>;
|
||||
typedef std::conditional_t<IsExclusive, ResolveValueType&&,
|
||||
const ResolveValueType&>
|
||||
ResolveValueTypeParam;
|
||||
|
||||
using RejectValueTypeParam =
|
||||
std::conditional_t<IsExclusive, RejectValueType&&,
|
||||
const RejectValueType&>;
|
||||
typedef std::conditional_t<IsExclusive, RejectValueType&&,
|
||||
const RejectValueType&>
|
||||
RejectValueTypeParam;
|
||||
|
||||
class AllSettledPromiseHolder : public MozPromiseRefcountable {
|
||||
public:
|
||||
|
|
@ -644,15 +648,15 @@ class MozPromise : public MozPromiseBase {
|
|||
* make the resolve/reject value argument "optional".
|
||||
*/
|
||||
template <typename ThisType, typename MethodType, typename ValueType>
|
||||
static std::enable_if_t<TakesAnyArguments<MethodType>,
|
||||
MethodReturnType<MethodType>>
|
||||
static std::enable_if_t<TakesArgument<MethodType>::value,
|
||||
typename detail::MethodTrait<MethodType>::ReturnType>
|
||||
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<!TakesAnyArguments<MethodType>,
|
||||
MethodReturnType<MethodType>>
|
||||
static std::enable_if_t<!TakesArgument<MethodType>::value,
|
||||
typename detail::MethodTrait<MethodType>::ReturnType>
|
||||
InvokeMethod(ThisType* aThisVal, MethodType aMethod, ValueType&& aValue) {
|
||||
return (aThisVal->*aMethod)();
|
||||
}
|
||||
|
|
@ -693,14 +697,18 @@ class MozPromise : public MozPromiseBase {
|
|||
: public ThenValueBase {
|
||||
friend class ThenCommand<ThenValue>;
|
||||
|
||||
using R1 = RemoveSmartPointer<MethodReturnType<ResolveMethodType>>;
|
||||
using R2 = RemoveSmartPointer<MethodReturnType<RejectMethodType>>;
|
||||
constexpr static bool SupportChaining =
|
||||
IsMozPromise<R1> && std::is_same_v<R1, R2>;
|
||||
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>>;
|
||||
|
||||
// Fall back to MozPromise when promise chaining is not supported to make
|
||||
// code compile.
|
||||
using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
|
||||
using PromiseType =
|
||||
std::conditional_t<SupportChaining::value, R1, MozPromise>;
|
||||
|
||||
public:
|
||||
ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
|
||||
|
|
@ -728,13 +736,13 @@ class MozPromise : public MozPromiseBase {
|
|||
|
||||
void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
|
||||
if (aValue.IsResolve()) {
|
||||
InvokeCallbackMethod<SupportChaining>(mThisVal.get(), mResolveMethod,
|
||||
MaybeMove(aValue.ResolveValue()),
|
||||
std::move(mCompletionPromise));
|
||||
InvokeCallbackMethod<SupportChaining::value>(
|
||||
mThisVal.get(), mResolveMethod, MaybeMove(aValue.ResolveValue()),
|
||||
std::move(mCompletionPromise));
|
||||
} else {
|
||||
InvokeCallbackMethod<SupportChaining>(mThisVal.get(), mRejectMethod,
|
||||
MaybeMove(aValue.RejectValue()),
|
||||
std::move(mCompletionPromise));
|
||||
InvokeCallbackMethod<SupportChaining::value>(
|
||||
mThisVal.get(), mRejectMethod, MaybeMove(aValue.RejectValue()),
|
||||
std::move(mCompletionPromise));
|
||||
}
|
||||
|
||||
// Null out mThisVal after invoking the callback so that any references
|
||||
|
|
@ -756,12 +764,15 @@ class MozPromise : public MozPromiseBase {
|
|||
class ThenValue<ThisType*, ResolveRejectMethodType> : public ThenValueBase {
|
||||
friend class ThenCommand<ThenValue>;
|
||||
|
||||
using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectMethodType>>;
|
||||
constexpr static bool SupportChaining = IsMozPromise<R1>;
|
||||
using R1 = typename RemoveSmartPointer<typename detail::MethodTrait<
|
||||
ResolveRejectMethodType>::ReturnType>::Type;
|
||||
using SupportChaining =
|
||||
std::integral_constant<bool, IsMozPromise<R1>::value>;
|
||||
|
||||
// Fall back to MozPromise when promise chaining is not supported to make
|
||||
// code compile.
|
||||
using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
|
||||
using PromiseType =
|
||||
std::conditional_t<SupportChaining::value, R1, MozPromise>;
|
||||
|
||||
public:
|
||||
ThenValue(nsISerialEventTarget* aResponseTarget, ThisType* aThisVal,
|
||||
|
|
@ -787,7 +798,7 @@ class MozPromise : public MozPromiseBase {
|
|||
}
|
||||
|
||||
void DoResolveOrRejectInternal(ResolveOrRejectValue& aValue) override {
|
||||
InvokeCallbackMethod<SupportChaining>(
|
||||
InvokeCallbackMethod<SupportChaining::value>(
|
||||
mThisVal.get(), mResolveRejectMethod, MaybeMove(aValue),
|
||||
std::move(mCompletionPromise));
|
||||
|
||||
|
|
@ -811,14 +822,18 @@ class MozPromise : public MozPromiseBase {
|
|||
class ThenValue<ResolveFunction, RejectFunction> : public ThenValueBase {
|
||||
friend class ThenCommand<ThenValue>;
|
||||
|
||||
using R1 = RemoveSmartPointer<MethodReturnType<ResolveFunction>>;
|
||||
using R2 = RemoveSmartPointer<MethodReturnType<RejectFunction>>;
|
||||
constexpr static bool SupportChaining =
|
||||
IsMozPromise<R1> && std::is_same_v<R1, R2>;
|
||||
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>>;
|
||||
|
||||
// Fall back to MozPromise when promise chaining is not supported to make
|
||||
// code compile.
|
||||
using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
|
||||
using PromiseType =
|
||||
std::conditional_t<SupportChaining::value, R1, MozPromise>;
|
||||
|
||||
public:
|
||||
ThenValue(nsISerialEventTarget* aResponseTarget,
|
||||
|
|
@ -852,11 +867,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>(
|
||||
InvokeCallbackMethod<SupportChaining::value>(
|
||||
mResolveFunction.ptr(), &ResolveFunction::operator(),
|
||||
MaybeMove(aValue.ResolveValue()), std::move(mCompletionPromise));
|
||||
} else {
|
||||
InvokeCallbackMethod<SupportChaining>(
|
||||
InvokeCallbackMethod<SupportChaining::value>(
|
||||
mRejectFunction.ptr(), &RejectFunction::operator(),
|
||||
MaybeMove(aValue.RejectValue()), std::move(mCompletionPromise));
|
||||
}
|
||||
|
|
@ -881,12 +896,15 @@ class MozPromise : public MozPromiseBase {
|
|||
class ThenValue<ResolveRejectFunction> : public ThenValueBase {
|
||||
friend class ThenCommand<ThenValue>;
|
||||
|
||||
using R1 = RemoveSmartPointer<MethodReturnType<ResolveRejectFunction>>;
|
||||
constexpr static bool SupportChaining = IsMozPromise<R1>;
|
||||
using R1 = typename RemoveSmartPointer<
|
||||
typename detail::MethodTrait<ResolveRejectFunction>::ReturnType>::Type;
|
||||
using SupportChaining =
|
||||
std::integral_constant<bool, IsMozPromise<R1>::value>;
|
||||
|
||||
// Fall back to MozPromise when promise chaining is not supported to make
|
||||
// code compile.
|
||||
using PromiseType = std::conditional_t<SupportChaining, R1, MozPromise>;
|
||||
using PromiseType =
|
||||
std::conditional_t<SupportChaining::value, R1, MozPromise>;
|
||||
|
||||
public:
|
||||
ThenValue(nsISerialEventTarget* aResponseTarget,
|
||||
|
|
@ -917,7 +935,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>(
|
||||
InvokeCallbackMethod<SupportChaining::value>(
|
||||
mResolveRejectFunction.ptr(), &ResolveRejectFunction::operator(),
|
||||
MaybeMove(aValue), std::move(mCompletionPromise));
|
||||
|
||||
|
|
@ -980,7 +998,7 @@ class MozPromise : public MozPromiseBase {
|
|||
MozPromise* aReceiver)
|
||||
: mCallSite(aCallSite), mThenValue(aThenValue), mReceiver(aReceiver) {}
|
||||
|
||||
ThenCommand(ThenCommand&& aOther) noexcept = default;
|
||||
ThenCommand(ThenCommand&& aOther) = default;
|
||||
|
||||
public:
|
||||
~ThenCommand() {
|
||||
|
|
@ -995,7 +1013,7 @@ class MozPromise : public MozPromiseBase {
|
|||
// p->Then(thread2, ...);
|
||||
operator RefPtr<PromiseType>() {
|
||||
static_assert(
|
||||
ThenValueType::SupportChaining,
|
||||
ThenValueType::SupportChaining::value,
|
||||
"The resolve/reject callback needs to return a RefPtr<MozPromise> "
|
||||
"in order to do promise chaining.");
|
||||
|
||||
|
|
@ -1318,18 +1336,12 @@ class MozPromise<ResolveValueT, RejectValueT, IsExclusive>::Private
|
|||
};
|
||||
|
||||
// A generic promise type that does the trick for simple use cases.
|
||||
//
|
||||
// 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>;
|
||||
typedef MozPromise<bool, nsresult, /* IsExclusive = */ true> GenericPromise;
|
||||
|
||||
// A generic, non-exclusive promise type that does the trick for simple use
|
||||
// cases.
|
||||
//
|
||||
// Vaguely deprecated, as above.
|
||||
using GenericNonExclusivePromise =
|
||||
MozPromise<bool, nsresult, /* IsExclusive = */ false>;
|
||||
typedef MozPromise<bool, nsresult, /* IsExclusive = */ false>
|
||||
GenericNonExclusivePromise;
|
||||
|
||||
/*
|
||||
* Class to encapsulate a promise for a particular role. Use this as the member
|
||||
|
|
@ -1340,9 +1352,8 @@ class MozPromiseHolderBase {
|
|||
public:
|
||||
MozPromiseHolderBase() = default;
|
||||
|
||||
MozPromiseHolderBase(MozPromiseHolderBase&& aOther) noexcept = default;
|
||||
MozPromiseHolderBase& operator=(MozPromiseHolderBase&& aOther) noexcept =
|
||||
default;
|
||||
MozPromiseHolderBase(MozPromiseHolderBase&& aOther) = default;
|
||||
MozPromiseHolderBase& operator=(MozPromiseHolderBase&& aOther) = default;
|
||||
|
||||
~MozPromiseHolderBase() { MOZ_ASSERT(!mPromise); }
|
||||
|
||||
|
|
@ -1689,10 +1700,38 @@ class ProxyFunctionRunnable : public CancelableRunnable {
|
|||
UniquePtr<FunctionStorage> mFunction;
|
||||
};
|
||||
|
||||
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;
|
||||
// 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.
|
||||
|
||||
// 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 {};
|
||||
|
||||
// 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.
|
||||
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>");
|
||||
MOZ_ASSERT(aTarget);
|
||||
typedef typename RemoveSmartPointer<decltype(aFunction())>::Type PromiseType;
|
||||
typedef detail::ProxyFunctionRunnable<Function, PromiseType>
|
||||
ProxyRunnableType;
|
||||
|
||||
auto p = MakeRefPtr<typename PromiseType::Private>(aCallerName);
|
||||
auto r = MakeRefPtr<ProxyRunnableType>(p, std::forward<Function>(aFunction));
|
||||
aTarget->Dispatch(r.forget());
|
||||
return p;
|
||||
}
|
||||
|
||||
} // namespace detail
|
||||
|
||||
|
|
@ -1704,18 +1743,9 @@ static auto InvokeAsync(nsISerialEventTarget* aTarget, const char* aCallerName,
|
|||
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 RemoveSmartPointer<decltype(aFunction())> PromiseType;
|
||||
typedef detail::ProxyFunctionRunnable<Function, PromiseType>
|
||||
ProxyRunnableType;
|
||||
|
||||
auto p = MakeRefPtr<typename PromiseType::Private>(aCallerName);
|
||||
auto r = MakeRefPtr<ProxyRunnableType>(p, std::forward<Function>(aFunction));
|
||||
aTarget->Dispatch(r.forget());
|
||||
return p;
|
||||
return detail::InvokeAsync(aTarget, aCallerName,
|
||||
detail::AllowInvokeAsyncFunctionLVRef(),
|
||||
std::forward<Function>(aFunction));
|
||||
}
|
||||
|
||||
# undef PROMISE_LOG
|
||||
|
|
|
|||
|
|
@ -562,40 +562,71 @@ 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 {
|
||||
using Type = T;
|
||||
typedef T Type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveSmartPointerHelper<RefPtr<T>> {
|
||||
using Type = T;
|
||||
template <typename T, typename Pointee>
|
||||
struct RemoveSmartPointerHelper<T, RefPtr<Pointee>> {
|
||||
typedef Pointee Type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveSmartPointerHelper<nsCOMPtr<T>> {
|
||||
using Type = T;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveRawOrSmartPointerHelper {
|
||||
using Type = typename RemoveSmartPointerHelper<T>::Type;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct RemoveRawOrSmartPointerHelper<T*> {
|
||||
using Type = T;
|
||||
template <typename T, typename Pointee>
|
||||
struct RemoveSmartPointerHelper<T, nsCOMPtr<Pointee>> {
|
||||
typedef Pointee Type;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
using RemoveSmartPointer =
|
||||
typename detail::RemoveSmartPointerHelper<std::remove_cv_t<T>>::Type;
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
} // namespace detail
|
||||
|
||||
template <typename T>
|
||||
using RemoveRawOrSmartPointer =
|
||||
typename detail::RemoveRawOrSmartPointerHelper<std::remove_cv_t<T>>::Type;
|
||||
struct RemoveRawOrSmartPointer
|
||||
: detail::RemoveRawOrSmartPointerHelper<T, std::remove_cv_t<T>> {};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
|
|
@ -766,22 +797,23 @@ struct nsRunnableMethodTraits;
|
|||
template <typename PtrType, class C, typename R, bool Owning,
|
||||
mozilla::RunnableKind Kind, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R (C::*)(As...), Owning, Kind> {
|
||||
using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>;
|
||||
typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(std::is_base_of<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
using return_type = R;
|
||||
using base_type = nsRunnableMethod<C, R, Owning, Kind>;
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
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> {
|
||||
using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>;
|
||||
typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type
|
||||
class_type;
|
||||
static_assert(std::is_base_of<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
using return_type = R;
|
||||
using base_type = nsRunnableMethod<C, R, Owning, Kind>;
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
|
||||
};
|
||||
|
||||
|
|
@ -790,22 +822,22 @@ template <typename PtrType, class C, typename R, bool Owning,
|
|||
mozilla::RunnableKind Kind, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R (__stdcall C::*)(As...), Owning,
|
||||
Kind> {
|
||||
using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>;
|
||||
typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(std::is_base_of<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
using return_type = R;
|
||||
using base_type = nsRunnableMethod<C, R, Owning, Kind>;
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
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> {
|
||||
using class_type = mozilla::RemoveRawOrSmartPointer<PtrType>;
|
||||
typedef typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type class_type;
|
||||
static_assert(std::is_base_of<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
using return_type = R;
|
||||
using base_type = nsRunnableMethod<C, R, Owning, Kind>;
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
|
||||
};
|
||||
|
||||
|
|
@ -813,11 +845,12 @@ template <typename PtrType, class C, typename R, bool Owning,
|
|||
mozilla::RunnableKind Kind, typename... As>
|
||||
struct nsRunnableMethodTraits<PtrType, R (__stdcall C::*)(As...) const, Owning,
|
||||
Kind> {
|
||||
using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>;
|
||||
typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type
|
||||
class_type;
|
||||
static_assert(std::is_base_of<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
using return_type = R;
|
||||
using base_type = nsRunnableMethod<C, R, Owning, Kind>;
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
|
||||
};
|
||||
|
||||
|
|
@ -825,11 +858,12 @@ template <typename PtrType, class C, typename R, bool Owning,
|
|||
mozilla::RunnableKind Kind>
|
||||
struct nsRunnableMethodTraits<PtrType, R (NS_STDCALL C::*)() const, Owning,
|
||||
Kind> {
|
||||
using class_type = const mozilla::RemoveRawOrSmartPointer<PtrType>;
|
||||
typedef const typename mozilla::RemoveRawOrSmartPointer<PtrType>::Type
|
||||
class_type;
|
||||
static_assert(std::is_base_of<C, class_type>::value,
|
||||
"Stored class must inherit from method's class");
|
||||
using return_type = R;
|
||||
using base_type = nsRunnableMethod<C, R, Owning, Kind>;
|
||||
typedef R return_type;
|
||||
typedef nsRunnableMethod<C, R, Owning, Kind> base_type;
|
||||
static const bool can_cancel = Kind == mozilla::RunnableKind::Cancelable;
|
||||
};
|
||||
# endif
|
||||
|
|
@ -846,6 +880,19 @@ 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 <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>;
|
||||
|
|
@ -859,6 +906,19 @@ template <typename S>
|
|||
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>;
|
||||
|
|
@ -936,6 +996,32 @@ 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>
|
||||
|
|
@ -949,8 +1035,69 @@ template <class>
|
|||
static auto HasRefCountMethodsTest(long) -> std::false_type;
|
||||
|
||||
template <class T>
|
||||
constexpr static bool HasRefCountMethods =
|
||||
decltype(HasRefCountMethodsTest<T>(0))::value;
|
||||
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;
|
||||
};
|
||||
|
||||
template <typename TWithoutPointer>
|
||||
struct PointerStorageClass
|
||||
: std::conditional<
|
||||
HasRefCountMethods<TWithoutPointer>::value,
|
||||
StoreRefPtrPassByPtr<TWithoutPointer>,
|
||||
typename NonnsISupportsPointerStorageClass<TWithoutPointer>::Type> {
|
||||
using Type = typename PointerStorageClass::conditional::type;
|
||||
};
|
||||
|
||||
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 SmartPointerStorageClass
|
||||
: std::conditional<
|
||||
mozilla::IsRefcountedSmartPointer<T>::value,
|
||||
StoreRefPtrPassByPtr<typename mozilla::RemoveSmartPointer<T>::Type>,
|
||||
StoreCopyPassByConstLRef<T>> {
|
||||
using Type = typename SmartPointerStorageClass::conditional::type;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
// Choose storage&passing strategy based on preferred storage type:
|
||||
// - If IsParameterStorageClass<T>::value is true, use as-is.
|
||||
|
|
@ -964,86 +1111,18 @@ constexpr static bool HasRefCountMethods =
|
|||
// - 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.)
|
||||
|
||||
// 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 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 T>
|
||||
struct OtherParameterStorage<T*> {
|
||||
using Type = StorePtrPassByPtr<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OtherParameterStorage<const T&> {
|
||||
using Type = StoreConstRefPassByConstLRef<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OtherParameterStorage<T&> {
|
||||
using Type = StoreRefPassByLRef<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OtherParameterStorage<RefPtr<T>> {
|
||||
using Type = StoreRefPtrPassByPtr<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct OtherParameterStorage<nsCOMPtr<T>> {
|
||||
using Type = StoreRefPtrPassByPtr<T>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
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;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ParameterStorage {
|
||||
using Type = typename ParameterStorageHelper<T>::Type;
|
||||
struct ParameterStorage
|
||||
: std::conditional<IsParameterStorageClass<T>::value, T,
|
||||
typename NonParameterStorageClass<T>::Type> {
|
||||
using Type = typename ParameterStorage::conditional::type;
|
||||
};
|
||||
|
||||
template <class T>
|
||||
|
|
|
|||
Loading…
Reference in a new issue