From 5ecb5d2d8c9b746ad781ff102ffdf8335c397fd9 Mon Sep 17 00:00:00 2001 From: yamashi Date: Tue, 16 Feb 2021 16:57:31 +0100 Subject: [PATCH] Add Lockable/Locked to wrap data we want to move around threads --- Code/core/include/Lockable.hpp | 68 ++++++++++++++++++++++++++++++++++ Code/core/include/Locked.hpp | 52 ++++++++++++++++++++++++++ Code/tests/src/core.cpp | 25 +++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 Code/core/include/Lockable.hpp create mode 100644 Code/core/include/Locked.hpp diff --git a/Code/core/include/Lockable.hpp b/Code/core/include/Lockable.hpp new file mode 100644 index 0000000..c311212 --- /dev/null +++ b/Code/core/include/Lockable.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include "Stl.hpp" + +namespace TiltedPhoques +{ + template + struct Locked; + + template + struct Lockable + { + struct Data + { + template + Data(Args&& ... aArgs) + : Value(std::forward(aArgs)...) + {} + + T Value; + TLock Lock; + }; + + struct Ref + { + Ref(typename SharedPtr::weak_type apData) + : m_pData(std::move(apData)) + {} + + [[nodiscard]] Locked Lock() const + { + if (auto locked = m_pData.lock()) + { + return { locked }; + } + + return { {} }; + } + + private: + typename SharedPtr::weak_type m_pData; + }; + + + template + Lockable(Args&& ... aArgs) + : m_pData(MakeShared(std::forward(aArgs)...)) + {} + + Ref AsRef() const noexcept + { + return Ref(m_pData); + } + + [[nodiscard]] Locked Lock() const + { + return AsRef().Lock(); + } + + private: + + friend struct Locked; + + SharedPtr m_pData; + }; +} + +#include "Locked.hpp" diff --git a/Code/core/include/Locked.hpp b/Code/core/include/Locked.hpp new file mode 100644 index 0000000..35575c2 --- /dev/null +++ b/Code/core/include/Locked.hpp @@ -0,0 +1,52 @@ +#pragma once + +#include "Lockable.hpp" + +namespace TiltedPhoques +{ + template + struct Locked + { + Locked(SharedPtr::Data> apData) + : m_pData(std::move(apData)) + , m_handle(m_pData->Lock) + { + } + + operator typename Lockable::Ref() const + { + return { m_pData }; + } + + bool IsValid() const + { + return (bool)m_pData; + } + + operator T& () + { + return Get(); + } + + operator T&() const + { + return Get(); + } + + const T& Get() const noexcept + { + return m_pData->Value; + } + + T& Get() noexcept + { + return m_pData->Value; + } + + private: + friend struct Lockable; + + SharedPtr::Data> m_pData; + std::scoped_lock m_handle; + }; +} diff --git a/Code/tests/src/core.cpp b/Code/tests/src/core.cpp index 2423e85..6ca50bb 100644 --- a/Code/tests/src/core.cpp +++ b/Code/tests/src/core.cpp @@ -13,6 +13,7 @@ #include "TaskQueue.hpp" #include "Initializer.hpp" #include "Serialization.hpp" +#include "Lockable.hpp" #include #include @@ -167,6 +168,30 @@ TEST_CASE("Containers") } } +TEST_CASE("Lockable") +{ + GIVEN("A lockable") + { + Lockable test("test"); + auto ref = test.AsRef(); + + { + auto locked = test.Lock(); + String& data = locked; + + REQUIRE(data == "test"); + } + + { + auto locked = ref.Lock(); + String& data = locked; + data = "toto"; + + REQUIRE(data == "toto"); + } + } +} + TEST_CASE("Making sure allocator stacks work corrently", "[core.allocator.stack]") { GIVEN("No allocator has been pushed")