123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501 |
- /*******************************************************************************
- The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
- Technology released in source code form as part of the game integration package.
- The content of this file may not be used without valid licenses to the
- AUDIOKINETIC Wwise Technology.
- Note that the use of the game engine is subject to the Unreal(R) Engine End User
- License Agreement at https://www.unrealengine.com/en-US/eula/unreal
- License Usage
- Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
- this file in accordance with the end user license agreement provided with the
- software or, alternatively, in accordance with the terms contained
- in a written agreement between you and Audiokinetic Inc.
- Copyright (c) 2023 Audiokinetic Inc.
- *******************************************************************************/
- #include "Wwise/WwiseUnitTests.h"
- #if WWISE_UNIT_TESTS
- #include "Wwise/WwiseExecutionQueue.h"
- #include <atomic>
- WWISE_TEST_CASE(Concurrency_ExecutionQueue_Smoke, "Wwise::Concurrency::ExecutionQueue_Smoke", "[ApplicationContextMask][SmokeFilter]")
- {
- SECTION("Static")
- {
- static_assert(std::is_constructible<FWwiseExecutionQueue, const TCHAR*>::value, "Can create a named Execution Queue");
- static_assert(std::is_constructible<FWwiseExecutionQueue, const TCHAR*, EWwiseTaskPriority>::value, "Can create a named Execution Queue with its own task priority");
- static_assert(!std::is_copy_constructible<FWwiseExecutionQueue>::value, "Cannot copy an Execution Queue");
- static_assert(!std::is_move_constructible<FWwiseExecutionQueue>::value, "Cannot move-construct an Execution Queue");
- static_assert(!std::is_copy_assignable<FWwiseExecutionQueue>::value, "Cannot assign an Execution Queue");
- static_assert(!std::is_move_assignable<FWwiseExecutionQueue>::value, "Cannot move-assign an Execution Queue");
- }
- SECTION("Instantiation")
- {
- FWwiseExecutionQueue NamedTask(WWISE_EQ_NAME("NamedTask Test"));
- FWwiseExecutionQueue PriorityTask(WWISE_EQ_NAME("PriorityTask Test"), EWwiseTaskPriority::Normal);
- }
- SECTION("Async At Destructor")
- {
- constexpr const int LoopCount = 10;
- std::atomic<int> Value{ 0 };
- {
- FWwiseExecutionQueue ExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < LoopCount; ++i)
- {
- ExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value]
- {
- ++Value;
- });
- }
- }
- CHECK(Value.load() == LoopCount);
- }
- SECTION("AsyncWait")
- {
- constexpr const int LoopCount = 10;
- std::atomic<int> Value{ 0 };
- {
- const auto CurrentThreadId = FPlatformTLS::GetCurrentThreadId();
- FWwiseExecutionQueue ExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < LoopCount; ++i)
- {
- ExecutionQueue.AsyncWait(WWISE_TEST_ASYNC_NAME, [&Value, CurrentThreadId]
- {
- CHECK_FALSE(CurrentThreadId == FPlatformTLS::GetCurrentThreadId());
- ++Value;
- });
- }
- CHECK(Value.load() == LoopCount);
- }
- }
- SECTION("Async in order")
- {
- constexpr const int LoopCount = 10;
- std::atomic<int> Value{ 0 };
- {
- FWwiseExecutionQueue ExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < LoopCount; ++i)
- {
- ExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value, ShouldBe = i]
- {
- CHECK(Value++ == ShouldBe);
- });
- }
- }
- CHECK(Value.load() == LoopCount);
- }
-
- SECTION("IsRunningInThisThread")
- {
- const auto CurrentThreadId = FPlatformTLS::GetCurrentThreadId();
- FWwiseExecutionQueue ExecutionQueue(WWISE_TEST_ASYNC_NAME);
- CHECK_FALSE(ExecutionQueue.IsRunningInThisThread());
- ExecutionQueue.AsyncWait(WWISE_TEST_ASYNC_NAME, [&ExecutionQueue, CurrentThreadId]
- {
- CHECK_FALSE(CurrentThreadId == FPlatformTLS::GetCurrentThreadId());
- CHECK(ExecutionQueue.IsRunningInThisThread());
- });
- CHECK_FALSE(ExecutionQueue.IsRunningInThisThread());
- }
- }
- WWISE_TEST_CASE(Concurrency_ExecutionQueue_Perf, "Wwise::Concurrency::ExecutionQueue_Perf", "[ApplicationContextMask][PerfFilter]")
- {
- SECTION("AsyncAddingOpPerf")
- {
- const bool bReduceLogVerbosity = FWwiseExecutionQueue::Test::bReduceLogVerbosity;
- FWwiseExecutionQueue::Test::bReduceLogVerbosity = true;
- ON_SCOPE_EXIT { FWwiseExecutionQueue::Test::bReduceLogVerbosity = bReduceLogVerbosity; };
- constexpr const int LoopCount = 500000;
- constexpr const int ExpectedUS = 600000;
- std::atomic<int> Value{ 0 };
- {
- FWwiseExecutionQueue ExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FDateTime StartTime = FDateTime::UtcNow();
- for (int i = 0; i < LoopCount; ++i)
- {
- ExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value]
- {
- ++Value;
- });
- }
- FTimespan Duration = FDateTime::UtcNow() - StartTime;
- WWISE_TEST_LOG("AsyncAddingOpPerf %dus < %dus", (int)Duration.GetTotalMicroseconds(), ExpectedUS);
- CHECK(Duration.GetTotalMicroseconds() < ExpectedUS);
- }
- CHECK(Value.load() == LoopCount);
- }
- SECTION("AsyncExecutionPerf")
- {
- const bool bReduceLogVerbosity = FWwiseExecutionQueue::Test::bReduceLogVerbosity;
- FWwiseExecutionQueue::Test::bReduceLogVerbosity = true;
- ON_SCOPE_EXIT { FWwiseExecutionQueue::Test::bReduceLogVerbosity = bReduceLogVerbosity; };
-
- constexpr const int LoopCount = 250000;
- constexpr const int ExpectedUS = 400000;
- std::atomic<int> Value{ 0 };
- FDateTime StartTime;
- {
- FWwiseExecutionQueue ExecutionQueue(WWISE_TEST_ASYNC_NAME);
- ExecutionQueue.AsyncWait(WWISE_TEST_ASYNC_NAME, [&ExecutionQueue, LoopCount, &Value]
- {
- for (int i = 0; i < LoopCount; ++i)
- {
- ExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value]
- {
- ++Value;
- });
- }
- });
- StartTime = FDateTime::UtcNow();
- }
- FTimespan Duration = FDateTime::UtcNow() - StartTime;
- WWISE_TEST_LOG("AsyncExecutionPerf %dus < %dus", (int)Duration.GetTotalMicroseconds(), ExpectedUS);
- CHECK(Value.load() == LoopCount);
- CHECK(Duration.GetTotalMicroseconds() < ExpectedUS);
- }
- }
- WWISE_TEST_CASE(Concurrency_ExecutionQueue, "Wwise::Concurrency::ExecutionQueue", "[ApplicationContextMask][ProductFilter]")
- {
- SECTION("Close")
- {
- std::atomic<int> Value{ 0 };
- std::atomic<int> OpenedQueues{ 0 };
- constexpr const int RepeatLoop = 2;
- constexpr const int MainLoopCount = 2;
- constexpr const int SubLoopCount = 2;
- constexpr const int FinalLoopCount = 2;
- constexpr const int LoopCount = RepeatLoop * MainLoopCount * SubLoopCount * FinalLoopCount;
- for (int Repeat = 0; Repeat < RepeatLoop; ++Repeat)
- {
- FWwiseExecutionQueue MainExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue* SubExecutionQueue = new FWwiseExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue DeletionExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < MainLoopCount; ++i)
- {
- MainExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value, &OpenedQueues, SubExecutionQueue, &DeletionExecutionQueue, SubLoopCount, FinalLoopCount]
- {
- for (int i = 0; i < SubLoopCount; ++i)
- {
- SubExecutionQueue->Async(WWISE_TEST_ASYNC_NAME, [&Value, &OpenedQueues, &DeletionExecutionQueue, FinalLoopCount]
- {
- ++OpenedQueues;
- auto ExecutionQueue = new FWwiseExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < FinalLoopCount; ++i)
- {
- ExecutionQueue->Async(WWISE_TEST_ASYNC_NAME, [&Value]
- {
- ++Value;
- });
- }
- DeletionExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&OpenedQueues, ExecutionQueue]
- {
- delete ExecutionQueue;
- --OpenedQueues;
- });
- });
- }
- });
- }
-
- MainExecutionQueue.Close();
- SubExecutionQueue->AsyncWait(WWISE_TEST_ASYNC_NAME, []{});
- SubExecutionQueue->CloseAndDelete();
- }
- CHECK(Value.load() == LoopCount);
- CHECK(OpenedQueues.load() == 0);
- }
- SECTION("Sleep on State Update")
- {
- const bool bMockSleepOnStateUpdate = FWwiseExecutionQueue::Test::bMockSleepOnStateUpdate;
- const bool bMockEngineDeletion = FWwiseExecutionQueue::Test::bMockEngineDeletion;
- FWwiseExecutionQueue::Test::bMockSleepOnStateUpdate = true;
- ON_SCOPE_EXIT
- {
- FWwiseExecutionQueue::Test::bMockSleepOnStateUpdate = bMockSleepOnStateUpdate;
- FWwiseExecutionQueue::Test::bMockEngineDeletion = bMockEngineDeletion;
- };
-
- std::atomic<int> Value{ 0 };
- constexpr const int RepeatLoop = 2;
- constexpr const int MainLoopCount = 2;
- constexpr const int SubLoopCount = 2;
- constexpr const int FinalLoopCount = 2;
- constexpr const int LoopCount = RepeatLoop * MainLoopCount * SubLoopCount * FinalLoopCount;
- for (int Repeat = 0; Repeat < RepeatLoop; ++Repeat)
- {
- FWwiseExecutionQueue MainExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue SubExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue DeletionExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < MainLoopCount; ++i)
- {
- if (i == MainLoopCount - 1)
- {
- MainExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, []
- {
- FWwiseExecutionQueue::Test::bMockEngineDeletion = true;
- });
- }
-
- MainExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value, &SubExecutionQueue, &DeletionExecutionQueue, SubLoopCount, FinalLoopCount]
- {
- for (int i = 0; i < SubLoopCount; ++i)
- {
- SubExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value, &DeletionExecutionQueue, FinalLoopCount]
- {
- auto ExecutionQueue = new FWwiseExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < FinalLoopCount; ++i)
- {
- ExecutionQueue->Async(WWISE_TEST_ASYNC_NAME, [&Value]
- {
- ++Value;
- });
- }
- DeletionExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [ExecutionQueue]
- {
- delete ExecutionQueue;
- });
- });
- }
- });
- }
-
- MainExecutionQueue.Close();
- SubExecutionQueue.Close();
- DeletionExecutionQueue.Close();
- FWwiseExecutionQueue::Test::bMockEngineDeletion = false;
- }
- CHECK(Value.load() == LoopCount);
- }
-
- SECTION("Async at exit")
- {
- const bool bMockEngineDeletion = FWwiseExecutionQueue::Test::bMockEngineDeletion;
- FWwiseExecutionQueue::Test::bMockEngineDeletion = true;
- ON_SCOPE_EXIT { FWwiseExecutionQueue::Test::bMockEngineDeletion = bMockEngineDeletion; };
-
- constexpr const int LoopCount = 10;
- std::atomic<int> Value{ 0 };
- {
- FWwiseExecutionQueue ExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < LoopCount; ++i)
- {
- ExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value, ShouldBe = i]
- {
- CHECK(Value++ == ShouldBe);
- });
- }
- }
- CHECK(Value.load() == LoopCount);
- }
- SECTION("Async after exit")
- {
- const bool bMockEngineDeleted = FWwiseExecutionQueue::Test::bMockEngineDeleted;
- FWwiseExecutionQueue::Test::bMockEngineDeleted = true;
- ON_SCOPE_EXIT { FWwiseExecutionQueue::Test::bMockEngineDeleted = bMockEngineDeleted; };
-
- constexpr const int LoopCount = 10;
- std::atomic<int> Value{ 0 };
- {
- const auto CurrentThreadId = FPlatformTLS::GetCurrentThreadId();
- FWwiseExecutionQueue::Test::bMockEngineDeleted = true;
- FWwiseExecutionQueue ExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < LoopCount; ++i)
- {
- ExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&Value, ShouldBe = i, CurrentThreadId]
- {
- CHECK(CurrentThreadId == FPlatformTLS::GetCurrentThreadId());
- CHECK(Value++ == ShouldBe);
- });
- }
- }
- CHECK(Value.load() == LoopCount);
- }
- }
- WWISE_TEST_CASE(Concurrency_ExecutionQueue_Stress, "Wwise::Concurrency::ExecutionQueue_Stress", "[ApplicationContextMask][StressFilter]")
- {
- SECTION("AsyncStress")
- {
- const bool bReduceLogVerbosity = FWwiseExecutionQueue::Test::bReduceLogVerbosity;
- FWwiseExecutionQueue::Test::bReduceLogVerbosity = !FWwiseExecutionQueue::Test::bExtremelyVerbose;
- ON_SCOPE_EXIT { FWwiseExecutionQueue::Test::bReduceLogVerbosity = bReduceLogVerbosity; };
-
- constexpr const int LoopCount = 2000000;
- constexpr const int MainLoopCount = 100;
- constexpr const int SubLoopCount = 100;
- constexpr const int FinalLoopCount = LoopCount / MainLoopCount / SubLoopCount;
- {
- FWwiseExecutionQueue MainExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue SubExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue DeletionExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < MainLoopCount; ++i)
- {
- MainExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&SubExecutionQueue, &DeletionExecutionQueue, SubLoopCount, FinalLoopCount]
- {
- for (int i = 0; i < SubLoopCount; ++i)
- {
- SubExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&DeletionExecutionQueue, FinalLoopCount]
- {
- auto ExecutionQueue = new FWwiseExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < FinalLoopCount; ++i)
- {
- ExecutionQueue->Async(WWISE_TEST_ASYNC_NAME, []
- {
- });
- }
- DeletionExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [ExecutionQueue]
- {
- delete ExecutionQueue;
- });
- });
- }
- });
- }
-
- MainExecutionQueue.Close();
- SubExecutionQueue.Close();
- }
- }
- SECTION("AsyncStress with Sleep")
- {
- const bool bReduceLogVerbosity = FWwiseExecutionQueue::Test::bReduceLogVerbosity;
- const bool bMockSleepOnStateUpdate = FWwiseExecutionQueue::Test::bMockSleepOnStateUpdate;
- FWwiseExecutionQueue::Test::bReduceLogVerbosity = !FWwiseExecutionQueue::Test::bExtremelyVerbose;
- FWwiseExecutionQueue::Test::bMockSleepOnStateUpdate = true;
- ON_SCOPE_EXIT
- {
- FWwiseExecutionQueue::Test::bReduceLogVerbosity = bReduceLogVerbosity;
- FWwiseExecutionQueue::Test::bMockSleepOnStateUpdate = bMockSleepOnStateUpdate;
- };
-
- constexpr const int LoopCount = 1000;
- constexpr const int MainLoopCount = 10;
- constexpr const int SubLoopCount = 10;
- constexpr const int FinalLoopCount = LoopCount / MainLoopCount / SubLoopCount;
- {
- FWwiseExecutionQueue MainExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue SubExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue DeletionExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < MainLoopCount; ++i)
- {
- MainExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&SubExecutionQueue, &DeletionExecutionQueue, SubLoopCount, FinalLoopCount]
- {
- for (int i = 0; i < SubLoopCount; ++i)
- {
- SubExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&DeletionExecutionQueue, FinalLoopCount]
- {
- auto ExecutionQueue = new FWwiseExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < FinalLoopCount; ++i)
- {
- ExecutionQueue->Async(WWISE_TEST_ASYNC_NAME, []
- {
- });
- }
- DeletionExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [ExecutionQueue]
- {
- delete ExecutionQueue;
- });
- });
- }
- });
- }
-
- MainExecutionQueue.Close();
- SubExecutionQueue.Close();
- }
- }
- SECTION("AsyncStress at Exit")
- {
- const bool bReduceLogVerbosity = FWwiseExecutionQueue::Test::bReduceLogVerbosity;
- const bool bMockEngineDeletion = FWwiseExecutionQueue::Test::bMockEngineDeletion;
- const bool bMockEngineDeleted = FWwiseExecutionQueue::Test::bMockEngineDeleted;
- FWwiseExecutionQueue::Test::bReduceLogVerbosity = !FWwiseExecutionQueue::Test::bExtremelyVerbose;
- ON_SCOPE_EXIT
- {
- FWwiseExecutionQueue::Test::bReduceLogVerbosity = bReduceLogVerbosity;
- FWwiseExecutionQueue::Test::bMockEngineDeletion = bMockEngineDeletion;
- FWwiseExecutionQueue::Test::bMockEngineDeleted = bMockEngineDeleted;
- };
-
- constexpr const int LoopCount = 100000;
- constexpr const int MainLoopCount = 100;
- constexpr const int SubLoopCount = 100;
- constexpr const int FinalLoopCount = LoopCount / MainLoopCount / SubLoopCount;
- {
- FWwiseExecutionQueue MainExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue SubExecutionQueue(WWISE_TEST_ASYNC_NAME);
- FWwiseExecutionQueue DeletionExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < MainLoopCount; ++i)
- {
- MainExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&SubExecutionQueue, &DeletionExecutionQueue, SubLoopCount, FinalLoopCount]
- {
- for (int i = 0; i < SubLoopCount; ++i)
- {
- SubExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [&DeletionExecutionQueue, FinalLoopCount]
- {
- auto ExecutionQueue = new FWwiseExecutionQueue(WWISE_TEST_ASYNC_NAME);
- for (int i = 0; i < FinalLoopCount; ++i)
- {
- ExecutionQueue->Async(WWISE_TEST_ASYNC_NAME, []
- {
- });
- }
- DeletionExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, [ExecutionQueue]
- {
- delete ExecutionQueue;
- });
- });
- }
- });
- if (i == MainLoopCount / 3)
- {
- MainExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, []
- {
- FWwiseExecutionQueue::Test::bMockEngineDeletion = true;
- });
- }
- }
- MainExecutionQueue.Async(WWISE_TEST_ASYNC_NAME, []
- {
- FWwiseExecutionQueue::Test::bMockEngineDeleted = true;
- });
-
- MainExecutionQueue.Close();
- SubExecutionQueue.Close();
- }
- }
- }
- #endif // WWISE_UNIT_TESTS
|