diff --git a/TRAP/src/Utils/Concurrency/Safe.h b/TRAP/src/Utils/Concurrency/Safe.h index 088c58460..7748c6e72 100644 --- a/TRAP/src/Utils/Concurrency/Safe.h +++ b/TRAP/src/Utils/Concurrency/Safe.h @@ -34,6 +34,17 @@ namespace TRAP::Utils template concept SupportsAtomic = std::integral || std::same_as; + +#ifdef TRACY_ENABLE + template + concept IsMutexMarkable = requires(Mutex mtx, const tracy::SourceLocationData* srcLoc) + { + { mtx.Mark(srcLoc) }; + }; +#else + template + concept IsMutexMarkable = false; +#endif } enum class AccessMode : u8 @@ -236,7 +247,11 @@ namespace TRAP::Utils : Lock(mutex, std::forward(otherLockArgs)...), m_value(value) { ZoneScoped; - LockMark(mutex); + + if constexpr(INTERNAL::IsMutexMarkable) + { + LockMark(mutex); + } } /// @brief Construct a read-only Access object from a const Safe object and any diff --git a/UnitTests/src/Utils/Concurrency/Safe.cpp b/UnitTests/src/Utils/Concurrency/Safe.cpp index 502897e96..3e029f3e9 100644 --- a/UnitTests/src/Utils/Concurrency/Safe.cpp +++ b/UnitTests/src/Utils/Concurrency/Safe.cpp @@ -2,6 +2,21 @@ #include "Utils/Concurrency/Safe.h" +namespace +{ + using Mutex = TRAP::Utils::ContentionFreeSharedMutex<>; + + template + using ReadLock = std::shared_lock; + template + using WriteLock = std::unique_lock; + + template + using ReadAccess = TRAP::Utils::Safe::template ReadAccess; + template + using WriteAccess = TRAP::Utils::Safe::template WriteAccess; +} + TEST_CASE("TRAP::Utils::AccessTraits", "[utils][concurrency][accesstraits]") { STATIC_REQUIRE_FALSE(TRAP::Utils::AccessTraits::IsReadOnly); @@ -162,12 +177,12 @@ TEST_CASE("TRAP::Utils::Safe::ReadAccess", "[utils][concurrency][safe][readacces SECTION("Constructors") { - TRAP::Utils::INTERNAL::DefaultMutex mtx{}; + Mutex mtx{}; //Value, mutex constructor { const std::string str = "Hello World!"; - TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + ReadAccess access{str, mtx}; } //Safe constructor @@ -179,85 +194,85 @@ TEST_CASE("TRAP::Utils::Safe::ReadAccess", "[utils][concurrency][safe][readacces //Copy constructor // { // const std::string str = "Hello World!"; - // TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + // ReadAccess access{str, mtx}; - // const TRAP::Utils::Safe::ReadAccess<> accessCopy(access); //Not allowed + // const ReadAccess accessCopy(access); //Not allowed // } //Copy constructor (read->write access) // { // std::string str = "Hello World!"; - // TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + // ReadAccess access{str, mtx}; - // const TRAP::Utils::Safe::WriteAccess<> accessCopy(access); //Not allowed + // const WriteAccess accessCopy(access); //Not allowed // } //Move constructor { const std::string str = "Hello World!"; - TRAP::Utils::Safe::ReadAccess<> access(str, mtx); + ReadAccess access(str, mtx); - const TRAP::Utils::Safe::ReadAccess<> accessMove(std::move(access)); + const ReadAccess accessMove(std::move(access)); } //Move constructor (read->write access) // { // std::string str = "Hello World!"; - // TRAP::Utils::Safe::ReadAccess<> access(str, mtx); + // ReadAccess access(str, mtx); - // const TRAP::Utils::Safe::WriteAccess<> accessMove(std::move(access)); //Not allowed + // const WriteAccess accessMove(std::move(access)); //Not allowed // } } SECTION("Assignments") { - TRAP::Utils::INTERNAL::DefaultMutex mtx{}; + Mutex mtx{}; //Copy assignment operator // { // const std::string str = "Hello World!"; - // TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + // ReadAccess access{str, mtx}; - // const TRAP::Utils::Safe::ReadAccess<> accessCopy = access; //Deleted + // const ReadAccess accessCopy = access; //Deleted // } //Copy assignment operator (read->write access) // { // const std::string str = "Hello World!"; - // TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + // ReadAccess access{str, mtx}; - // const TRAP::Utils::Safe::WriteAccess<> accessCopy = access; //Deleted + // const WriteAccess accessCopy = access; //Deleted // } //Move assignment operator { const std::string str = "Hello World!"; - TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + ReadAccess access{str, mtx}; - const TRAP::Utils::Safe::ReadAccess<> accessMove = std::move(access); + const ReadAccess accessMove = std::move(access); } //Move assignment operator (read->write access) // { // const std::string str = "Hello World!"; - // TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + // ReadAccess access{str, mtx}; - // const TRAP::Utils::Safe::WriteAccess<> accessMove = std::move(access); + // const WriteAccess accessMove = std::move(access); // } } SECTION("operator->()") { - TRAP::Utils::INTERNAL::DefaultMutex mtx{}; + Mutex mtx{}; const std::string str = "Hello World!"; { - const TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + const ReadAccess access{str, mtx}; REQUIRE_FALSE(access->empty()); } { - TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + ReadAccess access{str, mtx}; REQUIRE_FALSE(access->empty()); } @@ -265,16 +280,16 @@ TEST_CASE("TRAP::Utils::Safe::ReadAccess", "[utils][concurrency][safe][readacces SECTION("operator*()") { - TRAP::Utils::INTERNAL::DefaultMutex mtx{}; + Mutex mtx{}; const std::string str = "Hello World!"; { - const TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + const ReadAccess access{str, mtx}; REQUIRE_FALSE((*access).empty()); } { - TRAP::Utils::Safe::ReadAccess<> access{str, mtx}; + ReadAccess access{str, mtx}; REQUIRE_FALSE((*access).empty()); } @@ -292,12 +307,12 @@ TEST_CASE("TRAP::Utils::Safe::WriteAccess", "[utils][concurrency][safe][writeacc SECTION("Constructors") { - TRAP::Utils::INTERNAL::DefaultMutex mtx{}; + Mutex mtx{}; //Value, mutex constructor { std::string str = "Hello World!"; - TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + WriteAccess access{str, mtx}; } //Safe constructor @@ -309,69 +324,69 @@ TEST_CASE("TRAP::Utils::Safe::WriteAccess", "[utils][concurrency][safe][writeacc //Copy constructor // { // std::string str = "Hello World!"; - // TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + // WriteAccess access{str, mtx}; - // const TRAP::Utils::Safe::WriteAccess<> accessCopy(access); //Not allowed + // const WriteAccess accessCopy(access); //Not allowed // } //Copy constructor (write->read access) // { // std::string str = "Hello World!"; - // TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + // WriteAccess access{str, mtx}; - // const TRAP::Utils::Safe::ReadAccess<> accessCopy(access); //Not allowed + // const ReadAccess accessCopy(access); //Not allowed // } //Move constructor { std::string str = "Hello World!"; - TRAP::Utils::Safe::WriteAccess<> access(str, mtx); + WriteAccess access(str, mtx); - const TRAP::Utils::Safe::WriteAccess<> accessMove(std::move(access)); + const WriteAccess accessMove(std::move(access)); } //Move constructor (write->read access) // { // std::string str = "Hello World!"; - // TRAP::Utils::Safe::WriteAccess<> access(str, mtx); + // WriteAccess access(str, mtx); - // const TRAP::Utils::Safe::ReadAccess<> accessMove(std::move(access)); //Not allowed + // const ReadAccess accessMove(std::move(access)); //Not allowed // } } SECTION("Assignments") { - TRAP::Utils::INTERNAL::DefaultMutex mtx{}; + Mutex mtx{}; //Copy assignment operator (write->read access) // { // std::string str = "Hello World!"; - // TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + // WriteAccess access{str, mtx}; - // const TRAP::Utils::Safe::ReadAccess<> accessCopy = access; //Deleted + // const ReadAccess accessCopy = access; //Deleted // } //Move assignment operator (write->read access) // { // std::string str = "Hello World!"; - // TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + // WriteAccess access{str, mtx}; - // const TRAP::Utils::Safe::ReadAccess<> accessMove = std::move(access); + // const ReadAccess accessMove = std::move(access); // } } SECTION("operator->()") { - TRAP::Utils::INTERNAL::DefaultMutex mtx{}; + Mutex mtx{}; std::string str = "Hello World!"; { - const TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + const WriteAccess access{str, mtx}; REQUIRE_FALSE(access->empty()); } { - TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + WriteAccess access{str, mtx}; REQUIRE_FALSE(access->empty()); } @@ -379,16 +394,16 @@ TEST_CASE("TRAP::Utils::Safe::WriteAccess", "[utils][concurrency][safe][writeacc SECTION("operator*()") { - TRAP::Utils::INTERNAL::DefaultMutex mtx{}; + Mutex mtx{}; std::string str = "Hello World!"; { - const TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + const WriteAccess access{str, mtx}; REQUIRE_FALSE((*access).empty()); } { - TRAP::Utils::Safe::WriteAccess<> access{str, mtx}; + WriteAccess access{str, mtx}; REQUIRE_FALSE((*access).empty()); }