Files
UnrealEngine/Engine/Source/Programs/AutoRTFMTests/Private/QueueTests.cpp
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

81 lines
1.8 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "AutoRTFMTesting.h"
#include "Catch2Includes.h"
#include "Containers/TransactionallySafeSpscQueue.h"
#include <thread>
// Test loosely based on code from Containers/ConcurrentQueuesTest.cpp.
template <typename QueueType>
void TestSpscQueueCorrectness(int Num, bool bTransact)
{
QueueType Queue;
uint32 NumProduced = 0;
uint32 NumConsumed = 0;
std::thread ConsumeTask;
// Consumer
auto ConsumeLoop = [&Queue, &NumConsumed, Num]
{
while (NumConsumed != Num)
{
if (Queue.Dequeue().IsSet())
{
++NumConsumed;
}
}
};
// Producer
auto ProduceLoop = [&Queue, &NumProduced, Num]
{
do
{
Queue.Enqueue(typename QueueType::ElementType{});
}
while (++NumProduced != Num);
};
// Run the consumer loop on a helper thread.
UE_AUTORTFM_OPEN
{
ConsumeTask = std::thread{ConsumeLoop};
};
// Run the producer loop within a transaction.
if (bTransact)
{
AutoRTFM::Testing::Commit([&]
{
ProduceLoop();
});
}
else
{
ProduceLoop();
}
// Join the consumer thread to allow it to finish.
UE_AUTORTFM_OPEN
{
ConsumeTask.join();
};
// We should have produced and consumed exactly Num items, and the queue should be empty.
REQUIRE(NumProduced == Num);
REQUIRE(NumConsumed == Num);
REQUIRE(!Queue.Dequeue().IsSet());
}
TEST_CASE("TransactionallySafeSpscQueue")
{
// Non-transactional, trivial and complex types
TestSpscQueueCorrectness<TTransactionallySafeSpscQueue<int>>(10000, /*bTransact=*/false);
TestSpscQueueCorrectness<TTransactionallySafeSpscQueue<FString>>(10000, /*bTransact=*/false);
// Transactional, trivial and complex types
TestSpscQueueCorrectness<TTransactionallySafeSpscQueue<int>>(10000, /*bTransact=*/true);
TestSpscQueueCorrectness<TTransactionallySafeSpscQueue<FString>>(10000, /*bTransact=*/true);
}