From 2b567f31537e6ea7f804d76f359ae105e2cdff4b Mon Sep 17 00:00:00 2001 From: Andreas Leroux Date: Fri, 18 Oct 2024 16:17:24 +0200 Subject: [PATCH] BREAKING CHANGE: ecstasy::ResourceReference now use std::reference_wrapper when not thread safe Also removed the templated ecstasy::Resource and base ecstasy::ResourceBase classes, both replaced by the simplier IResource base class. Close #170 --- .github/workflows/build-tests.yml | 2 +- doc/Building.md | 2 +- doc/Glossary.md | 4 +- doc/Tutorial.md | 2 +- .../integrations/event/EventsManager.cpp | 19 +++-- .../integrations/event/inputs/Gamepads.hpp | 4 +- .../integrations/event/inputs/Keyboard.hpp | 4 +- .../integrations/event/inputs/Mouse.hpp | 4 +- .../integrations/sfml/systems/PollEvents.cpp | 4 +- .../integrations/user_action/PollActions.hpp | 6 +- .../integrations/user_action/Users.cpp | 4 +- .../integrations/user_action/Users.hpp | 4 +- src/ecstasy/query/concepts/Queryable.hpp | 2 +- src/ecstasy/registry/Registry.cpp | 8 +- src/ecstasy/registry/Registry.hpp | 16 ++-- .../registry/concepts/queryable_type.hpp | 6 +- src/ecstasy/resources/CMakeLists.txt | 4 +- src/ecstasy/resources/IResource.hpp | 40 ++++++++++ src/ecstasy/resources/ObjectWrapper.hpp | 55 +++++++++++++- src/ecstasy/resources/Resource.hpp | 73 ------------------- src/ecstasy/resources/entity/Entities.hpp | 4 +- src/ecstasy/resources/include.hpp | 2 +- src/ecstasy/thread/LockableView.hpp | 32 +++++++- tests/registry/tests_DeletionStack.cpp | 10 +-- tests/registry/tests_Registry.cpp | 32 ++++---- 25 files changed, 197 insertions(+), 146 deletions(-) create mode 100644 src/ecstasy/resources/IResource.hpp delete mode 100644 src/ecstasy/resources/Resource.hpp diff --git a/.github/workflows/build-tests.yml b/.github/workflows/build-tests.yml index 7cf031bef..aeed0389c 100644 --- a/.github/workflows/build-tests.yml +++ b/.github/workflows/build-tests.yml @@ -92,7 +92,7 @@ jobs: gcovr -r ${{github.workspace}} --exclude-unreachable-branches --exclude-throw-branches --xml --output ./coverage.xml -e "src/ecstasy/integrations/sfml/*" ${{github.workspace}}/build/src - name: Upload Coverage Data - if: matrix.GCOV && (secrets.CODECOV_TOKEN != '') && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name) + if: matrix.GCOV && (github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.event.pull_request.base.repo.full_name) uses: codecov/codecov-action@v3 with: token: ${{ secrets.CODECOV_TOKEN }} diff --git a/doc/Building.md b/doc/Building.md index f9e4fad9f..81302c795 100644 --- a/doc/Building.md +++ b/doc/Building.md @@ -98,7 +98,7 @@ _In case this documentation is not up to date with the [Options.cmake](/cmake/Op | ENABLE_COVERAGE | Enable code coverage tracking. Must be set with **BUILD_TEST_SUITE** to have the tests coverage | OFF | | BUILD_SHARED_LIBS | Build Ecstasy as shared libaries | OFF | | ECSTASY_THREAD_SAFE | Combination of **ECSTASY_AUTO_LOCK**, **ECSTASY_AUTO_LOCK_RESOURCES**, **ECSTASY_LOCKABLE_RESOURCES** and **ECSTASY_LOCKABLE_STORAGES** | OFF | -| ECSTASY_LOCKABLE_RESOURCES | Make [Resource](@ref ecstasy::Resource) inherit [SharedRecursiveMutex](@ref ecstasy::thread::SharedRecursiveMutex) | OFF | +| ECSTASY_LOCKABLE_RESOURCES | Make [IResource](@ref ecstasy::IResource) inherit [SharedRecursiveMutex](@ref ecstasy::thread::SharedRecursiveMutex) | OFF | | ECSTASY_LOCKABLE_STORAGES | Make [IStorage](@ref ecstasy::IStorage) inherit [SharedRecursiveMutex](@ref ecstasy::thread::SharedRecursiveMutex) | OFF | | ECSTASY_AUTO_LOCK | Auto lock lockable queryables in registry queries | OFF | | ECSTASY_AUTO_LOCK_RESOURCES | Auto lock resources with registry.getResource. Requires **ECSTASY_LOCKABLE_RESOURCES** | OFF | diff --git a/doc/Glossary.md b/doc/Glossary.md index 4d0a96e4e..f254a85dd 100644 --- a/doc/Glossary.md +++ b/doc/Glossary.md @@ -63,7 +63,7 @@ In ecstasy, the [Entities](@ref ecstasy::Entities) class is a resource present b A simple use case would be a Timer resource to improve our previous Movement system: ```cpp -class Timer : public ecstasy::Resource { +class Timer : public ecstasy::IResource { public: /// Creates a new timer. explicit Timer() noexcept : _lastReset(std::chrono::steady_clock::now()) {} @@ -99,7 +99,7 @@ struct Movement : public ecstasy::ISystem { }; ``` -References: [Resource](@ref ecstasy::Resource), [registry.addResource()](@ref ecstasy::Registry::addResource), [registry.getResource()](@ref ecstasy::Registry.getResource), [Entities](@ref ecstasy::Entities) +References: [IResource](@ref ecstasy::IResource), [registry.addResource()](@ref ecstasy::Registry::addResource), [registry.getResource()](@ref ecstasy::Registry.getResource), [Entities](@ref ecstasy::Entities) ## Registry diff --git a/doc/Tutorial.md b/doc/Tutorial.md index 0a4041165..f57e917f9 100644 --- a/doc/Tutorial.md +++ b/doc/Tutorial.md @@ -494,7 +494,7 @@ By default ecstasy is not thread safe. By not thread safe I mean there is absolu But no worries it is just some compilation options to set: -- @b ECSTASY_LOCKABLE_RESOURCES will make @ref Resource class validate the [Lockable](@ref ecstasy::thread::Lockable) concept. +- @b ECSTASY_LOCKABLE_RESOURCES will make @ref IResource class validate the [Lockable](@ref ecstasy::thread::Lockable) concept. - @b ECSTASY_LOCKABLE_STORAGES will make @ref IStorage class validate the [Lockable](@ref ecstasy::thread::Lockable) concept. - @b ECSTASY_AUTO_LOCK will lock any [Lockable](@ref ecstasy::thread::Lockable) queryables in any registry queries or registry modifiers. - @b ECSTASY_THREAD_SAFE will enable the three options above. diff --git a/src/ecstasy/integrations/event/EventsManager.cpp b/src/ecstasy/integrations/event/EventsManager.cpp index 09b4f30fe..56c3f8de2 100644 --- a/src/ecstasy/integrations/event/EventsManager.cpp +++ b/src/ecstasy/integrations/event/EventsManager.cpp @@ -90,7 +90,8 @@ namespace ecstasy::integration::event callListeners(registry, event.mouseButton); if (registry.hasResource()) - registry.getResource()->setButtonState(event.mouseButton.button, event.mouseButton.pressed); + registry.getResource().get().setButtonState( + event.mouseButton.button, event.mouseButton.pressed); break; case Event::Type::MouseWheelScrolled: callListeners(registry, event.mouseWheel); break; case Event::Type::MouseMoved: @@ -98,7 +99,8 @@ namespace ecstasy::integration::event if (registry.hasResource()) { RR mouse = registry.getResource(); - mouse->setPosition(event.mouseMove.x + mouse->getX(), event.mouseMove.y + mouse->getY()); + mouse.get().setPosition( + event.mouseMove.x + mouse.get().getX(), event.mouseMove.y + mouse.get().getY()); } break; case Event::Type::KeyPressed: @@ -106,7 +108,7 @@ namespace ecstasy::integration::event callKeyListeners(registry, event.key); if (registry.hasResource()) - registry.getResource()->setKeyState(event.key.key, event.key.pressed); + registry.getResource().get().setKeyState(event.key.key, event.key.pressed); break; case Event::Type::TextEntered: callListeners(registry, event.text); break; case Event::Type::GamepadButtonPressed: @@ -115,7 +117,8 @@ namespace ecstasy::integration::event if (registry.hasResource()) registry.getResource() - ->get(event.gamepadButton.id) + .get() + .get(event.gamepadButton.id) .setButtonState(event.gamepadButton.button, event.gamepadButton.pressed); break; case Event::Type::GamepadConnected: @@ -124,7 +127,8 @@ namespace ecstasy::integration::event if (registry.hasResource()) registry.getResource() - ->get(event.gamepadConnected.id) + .get() + .get(event.gamepadConnected.id) .setConnected(event.gamepadConnected.connected); break; case Event::Type::GamepadAxis: @@ -132,7 +136,8 @@ namespace ecstasy::integration::event if (registry.hasResource()) registry.getResource() - ->get(event.gamepadAxis.id) + .get() + .get(event.gamepadAxis.id) .setAxisValue(event.gamepadAxis.axis, event.gamepadAxis.value); break; default: break; @@ -140,7 +145,7 @@ namespace ecstasy::integration::event #ifdef ECSTASY_INTEGRATIONS_USER_ACTION if (registry.hasResource()) - registry.getResource()->handleEvent(registry, event); + registry.getResource().get().handleEvent(registry, event); #endif } } // namespace ecstasy::integration::event diff --git a/src/ecstasy/integrations/event/inputs/Gamepads.hpp b/src/ecstasy/integrations/event/inputs/Gamepads.hpp index 1fd17cb51..416b7cef2 100644 --- a/src/ecstasy/integrations/event/inputs/Gamepads.hpp +++ b/src/ecstasy/integrations/event/inputs/Gamepads.hpp @@ -13,7 +13,7 @@ #define ECSTASY_INTEGRATIONS_EVENT_INPUTS_GAMEPADS_HPP_ #include "Gamepad.hpp" -#include "ecstasy/resources/Resource.hpp" +#include "ecstasy/resources/IResource.hpp" namespace ecstasy::integration::event { @@ -23,7 +23,7 @@ namespace ecstasy::integration::event /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-11-18) /// - class Gamepads : public ecstasy::Resource { + class Gamepads : public ecstasy::IResource { public: /// @brief Number of supported gamepads. static const size_t GamepadCount = 4; diff --git a/src/ecstasy/integrations/event/inputs/Keyboard.hpp b/src/ecstasy/integrations/event/inputs/Keyboard.hpp index fe511e383..f95f86631 100644 --- a/src/ecstasy/integrations/event/inputs/Keyboard.hpp +++ b/src/ecstasy/integrations/event/inputs/Keyboard.hpp @@ -16,7 +16,7 @@ #include #include -#include "ecstasy/resources/Resource.hpp" +#include "ecstasy/resources/IResource.hpp" #include "util/serialization/SerializableEnum.hpp" namespace ecstasy::integration::event @@ -27,7 +27,7 @@ namespace ecstasy::integration::event /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-11-16) /// - class Keyboard : public Resource { + class Keyboard : public IResource { public: // LCOV_EXCL_START diff --git a/src/ecstasy/integrations/event/inputs/Mouse.hpp b/src/ecstasy/integrations/event/inputs/Mouse.hpp index 86dd5b7fb..fa45df259 100644 --- a/src/ecstasy/integrations/event/inputs/Mouse.hpp +++ b/src/ecstasy/integrations/event/inputs/Mouse.hpp @@ -16,7 +16,7 @@ #include #include -#include "ecstasy/resources/Resource.hpp" +#include "ecstasy/resources/IResource.hpp" #include "util/serialization/SerializableEnum.hpp" namespace ecstasy::integration::event @@ -27,7 +27,7 @@ namespace ecstasy::integration::event /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-11-04) /// - class Mouse : public Resource { + class Mouse : public IResource { public: // LCOV_EXCL_START diff --git a/src/ecstasy/integrations/sfml/systems/PollEvents.cpp b/src/ecstasy/integrations/sfml/systems/PollEvents.cpp index d6844e130..f1e74968e 100644 --- a/src/ecstasy/integrations/sfml/systems/PollEvents.cpp +++ b/src/ecstasy/integrations/sfml/systems/PollEvents.cpp @@ -67,7 +67,7 @@ namespace ecstasy::integration::sfml RR windowWrapper = registry.getResource(); sf::Event event; - while (windowWrapper->pollEvent(event)) { + while (windowWrapper.get().pollEvent(event)) { switch (event.type) { /// Mouse events case sf::Event::MouseButtonPressed: @@ -117,7 +117,7 @@ namespace ecstasy::integration::sfml event.joystickMove.position / 100.f)); break; - case sf::Event::Closed: windowWrapper->get().close(); break; + case sf::Event::Closed: windowWrapper.get()->close(); break; default: break; } } diff --git a/src/ecstasy/integrations/user_action/PollActions.hpp b/src/ecstasy/integrations/user_action/PollActions.hpp index bbda4b870..b24713ec9 100644 --- a/src/ecstasy/integrations/user_action/PollActions.hpp +++ b/src/ecstasy/integrations/user_action/PollActions.hpp @@ -49,9 +49,9 @@ namespace ecstasy::integration::user_action if (!registry.hasResource()) [[unlikely]] return; RR pendingActions = registry.getResource(); - while (!pendingActions->get().empty()) { - std::ignore = std::make_tuple((callListeners(registry, pendingActions->get().front()), 0)...); - pendingActions->get().pop(); + while (!pendingActions.get()->empty()) { + std::ignore = std::make_tuple((callListeners(registry, pendingActions.get()->front()), 0)...); + pendingActions.get()->pop(); } } diff --git a/src/ecstasy/integrations/user_action/Users.cpp b/src/ecstasy/integrations/user_action/Users.cpp index 69c97b4c0..bb344960f 100644 --- a/src/ecstasy/integrations/user_action/Users.cpp +++ b/src/ecstasy/integrations/user_action/Users.cpp @@ -27,7 +27,7 @@ namespace ecstasy::integration::user_action { if (!registry.hasResource()) [[unlikely]] return; - registry.getResource()->updateBindings(); + registry.getResource().get().updateBindings(); } void Users::updateBindings() @@ -61,7 +61,7 @@ namespace ecstasy::integration::user_action void Users::callActionListeners(Registry ®istry, Action action) { if (registry.hasResource()) - registry.getResource()->get().push(action); + registry.getResource().get()->push(action); for (auto [entity, maybeListener, maybeListeners] : registry.select, Maybe>() diff --git a/src/ecstasy/integrations/user_action/Users.hpp b/src/ecstasy/integrations/user_action/Users.hpp index d5dd30830..d85ae4e8e 100644 --- a/src/ecstasy/integrations/user_action/Users.hpp +++ b/src/ecstasy/integrations/user_action/Users.hpp @@ -19,7 +19,7 @@ #include "ecstasy/integrations/event/inputs/Keyboard.hpp" #include "ecstasy/integrations/event/inputs/Mouse.hpp" #include "ecstasy/registry/Registry.hpp" -#include "ecstasy/resources/Resource.hpp" +#include "ecstasy/resources/IResource.hpp" #include "ecstasy/storages/MapStorage.hpp" #include @@ -37,7 +37,7 @@ namespace ecstasy::integration::user_action /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-12-02) /// - class Users : public ecstasy::Resource { + class Users : public ecstasy::IResource { private: /// @brief Helper type instead of using @ref std::pair. /// Describe a link between an action and a user. diff --git a/src/ecstasy/query/concepts/Queryable.hpp b/src/ecstasy/query/concepts/Queryable.hpp index 75b049a89..2628d6ef5 100644 --- a/src/ecstasy/query/concepts/Queryable.hpp +++ b/src/ecstasy/query/concepts/Queryable.hpp @@ -217,7 +217,7 @@ namespace ecstasy::query /// template struct thread_safe_reference { - using type = T &; + using type = std::reference_wrapper; }; /// @copydoc thread_safe_reference diff --git a/src/ecstasy/registry/Registry.cpp b/src/ecstasy/registry/Registry.cpp index c4373103b..f22dbd784 100644 --- a/src/ecstasy/registry/Registry.cpp +++ b/src/ecstasy/registry/Registry.cpp @@ -15,7 +15,7 @@ namespace ecstasy { Registry::EntityBuilder::EntityBuilder(Registry ®istry) noexcept - : _registry(registry), _builder(registry.getResource()->builder()) + : _registry(registry), _builder(registry.getResource().get().builder()) { } @@ -37,7 +37,7 @@ namespace ecstasy Entity Registry::getEntity(Entity::Index index) { - return getResource()->get(index); + return getResource().get().get(index); } std::vector> Registry::getEntityStorages(Entity entity) @@ -51,7 +51,7 @@ namespace ecstasy bool Registry::eraseEntity(Entity entity) { - bool erased = getResource()->erase(entity); + bool erased = getResource().get().erase(entity); if (!erased) return false; @@ -61,7 +61,7 @@ namespace ecstasy size_t Registry::eraseEntities(std::span entities) { - size_t erased = getResource()->erase(entities); + size_t erased = getResource().get().erase(entities); if (!erased) return 0; diff --git a/src/ecstasy/registry/Registry.hpp b/src/ecstasy/registry/Registry.hpp index 8a0b1fa60..95992560e 100644 --- a/src/ecstasy/registry/Registry.hpp +++ b/src/ecstasy/registry/Registry.hpp @@ -49,6 +49,8 @@ namespace ecstasy /// @brief Resource reference type. /// This type is used to reference a resource in a thread-safe way depending on the AutoLock parameter. /// + /// @note Consider this as a thread_safe @ref std::reference_wrapper. + /// /// @tparam R Resource type. /// @tparam AutoLock Whether the resource should be locked automatically. /// @@ -95,7 +97,7 @@ namespace ecstasy } /// @copydoc getQueryable() - template R> + template R> requires query::Queryable [[nodiscard]] constexpr R &getQueryable() { @@ -137,7 +139,7 @@ namespace ecstasy } /// @copydoc getFromType() - template R> + template R> [[nodiscard]] constexpr R &getFromType() { return getResource(); @@ -847,7 +849,7 @@ namespace ecstasy /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-10-18) /// - template R, typename... Args> + template R, typename... Args> R &addResource(Args &&...args) { return _resources.emplace(std::forward(args)...); @@ -881,7 +883,7 @@ namespace ecstasy /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-11-06) /// - template R> + template R> [[nodiscard]] bool hasResource() const { return _resources.contains(); @@ -900,7 +902,7 @@ namespace ecstasy /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-10-18) /// - template R, bool Locked = thread::AUTO_LOCK_RESOURCES_DEFAULT> + template R, bool Locked = thread::AUTO_LOCK_RESOURCES_DEFAULT> [[nodiscard]] ResourceReference getResource() const { return _resources.get(); @@ -918,7 +920,7 @@ namespace ecstasy /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-10-18) /// - template R, bool Locked = thread::AUTO_LOCK_RESOURCES_DEFAULT> + template R, bool Locked = thread::AUTO_LOCK_RESOURCES_DEFAULT> [[nodiscard]] ResourceReference getResource() { return _resources.get(); @@ -1223,7 +1225,7 @@ namespace ecstasy private: /// @brief Registry resources. - Instances _resources; + Instances _resources; /// @brief Registry storages. Instances _storages; /// @brief Registry systems. diff --git a/src/ecstasy/registry/concepts/queryable_type.hpp b/src/ecstasy/registry/concepts/queryable_type.hpp index 80036eaf2..36f558ee4 100644 --- a/src/ecstasy/registry/concepts/queryable_type.hpp +++ b/src/ecstasy/registry/concepts/queryable_type.hpp @@ -15,7 +15,7 @@ #include "ecstasy/query/concepts/Modifier.hpp" #include "ecstasy/query/concepts/Queryable.hpp" #include "ecstasy/registry/concepts/RegistryModifier.hpp" -#include "ecstasy/resources/Resource.hpp" +#include "ecstasy/resources/IResource.hpp" #include "ecstasy/storages/StorageConcepts.hpp" namespace ecstasy @@ -24,7 +24,7 @@ namespace ecstasy /// @brief Try to get the type of a queryable associated to a type stored in the registry (component, storage, /// resource...). /// Returns C if: - /// - C is derived from the @ref ecstasy::Resource class and match the @ref Queryable concept. + /// - C is derived from the @ref ecstasy::IResource class and match the @ref Queryable concept. /// - C match the @ref ecstasy::IsStorage concept and match the @ref Queryable concept. /// - C is a const type matching the @ref ConstQueryableObject concept. /// - C match the @ref ecstasy::query::Modifier @@ -49,7 +49,7 @@ namespace ecstasy }; /// @copydoc queryable_type - template R> + template R> requires query::Queryable struct queryable_type { using type = R; diff --git a/src/ecstasy/resources/CMakeLists.txt b/src/ecstasy/resources/CMakeLists.txt index 6afadf2f1..3c8c638e4 100644 --- a/src/ecstasy/resources/CMakeLists.txt +++ b/src/ecstasy/resources/CMakeLists.txt @@ -7,6 +7,6 @@ set(SRC ${SRC} ${INCROOT}/include.hpp ${INCROOT}/ObjectWrapper.hpp - ${INCROOT}/Resource.hpp + ${INCROOT}/IResource.hpp PARENT_SCOPE -) \ No newline at end of file +) diff --git a/src/ecstasy/resources/IResource.hpp b/src/ecstasy/resources/IResource.hpp new file mode 100644 index 000000000..6b0ee5a89 --- /dev/null +++ b/src/ecstasy/resources/IResource.hpp @@ -0,0 +1,40 @@ +/// +/// @file IResource.hpp +/// @author Andréas Leroux (andreas.leroux@epitech.eu) +/// @brief Base class of all registry resources. +/// @version 1.0.0 +/// @date 2022-10-17 +/// +/// @copyright Copyright (c) ECSTASY 2022 - 2024 +/// +/// + +#ifndef ECSTASY_RESOURCE_IRESOURCE_HPP_ +#define ECSTASY_RESOURCE_IRESOURCE_HPP_ + +#include "ecstasy/config.hpp" + +#ifdef ECSTASY_LOCKABLE_RESOURCES + #include "ecstasy/thread/SharedRecursiveMutex.hpp" +#endif + +namespace ecstasy +{ + /// + /// @brief Base class of all registry resources. + /// + /// @author Andréas Leroux (andreas.leroux@epitech.eu) + /// @since 1.0.0 (2022-10-17) + /// + class IResource +#ifdef ECSTASY_LOCKABLE_RESOURCES + : public thread::SharedRecursiveMutex +#endif + { + public: + /// @brief Default destructor. + virtual ~IResource() = default; + }; // namespace ecstasy +} // namespace ecstasy + +#endif /* !ECSTASY_RESOURCE_IRESOURCE_HPP_ */ diff --git a/src/ecstasy/resources/ObjectWrapper.hpp b/src/ecstasy/resources/ObjectWrapper.hpp index 269a1b40c..012a0d483 100644 --- a/src/ecstasy/resources/ObjectWrapper.hpp +++ b/src/ecstasy/resources/ObjectWrapper.hpp @@ -12,7 +12,7 @@ #ifndef ECSTASY_RESOURCES_OBJECTWRAPPER_HPP_ #define ECSTASY_RESOURCES_OBJECTWRAPPER_HPP_ -#include "Resource.hpp" +#include "IResource.hpp" namespace ecstasy { @@ -25,7 +25,7 @@ namespace ecstasy /// @since 1.0.0 (2022-11-16) /// template - class ObjectWrapper : public Resource> { + class ObjectWrapper : public IResource { public: /// /// @brief Construct a new Object Wrapper. @@ -50,6 +50,57 @@ namespace ecstasy /// ~ObjectWrapper() = default; + /// + /// @brief Access the wrapped object. + /// + /// @return T& Reference to the wrapped object. + /// + /// @author Andréas Leroux (andreas.leroux@epitech.eu) + /// @since 1.0.0 (2024-10-18) + /// + [[nodiscard]] constexpr T &operator*() noexcept + { + return _object; + } + + /// + /// @brief Access the wrapped object. + /// + /// @return const T& Const reference to the wrapped object. + /// + /// @author Andréas Leroux (andreas.leroux@epitech.eu) + /// @since 1.0.0 (2024-10-18) + /// + [[nodiscard]] constexpr const T &operator*() const noexcept + { + return _object; + } + + /// + /// @brief Access the wrapped object pointer. + /// + /// @return T* Pointer to the wrapped object. + /// + /// @author Andréas Leroux (andreas.leroux@epitech.eu) + /// @since 1.0.0 (2024-10-18) + /// + [[nodiscard]] constexpr T *operator->() noexcept + { + return &_object; + } + + /// + /// @brief Access the wrapped object pointer. + /// + /// @return T const* Const pointer to the wrapped object. + /// @author Andréas Leroux (andreas.leroux@epitech.eu) + /// @since 1.0.0 (2024-10-18) + /// + [[nodiscard]] constexpr T const *operator->() const noexcept + { + return &_object; + } + /// /// @brief Get a reference to the object. /// diff --git a/src/ecstasy/resources/Resource.hpp b/src/ecstasy/resources/Resource.hpp deleted file mode 100644 index 15d363a91..000000000 --- a/src/ecstasy/resources/Resource.hpp +++ /dev/null @@ -1,73 +0,0 @@ -/// -/// @file Resource.hpp -/// @author Andréas Leroux (andreas.leroux@epitech.eu) -/// @brief Base class of all registry resources. -/// @version 1.0.0 -/// @date 2022-10-17 -/// -/// @copyright Copyright (c) ECSTASY 2022 - 2024 -/// -/// - -#ifndef ECSTASY_RESOURCE_RESOURCE_HPP_ -#define ECSTASY_RESOURCE_RESOURCE_HPP_ - -#include "ecstasy/config.hpp" - -#ifdef ECSTASY_LOCKABLE_RESOURCES - #include "ecstasy/thread/SharedRecursiveMutex.hpp" -#endif - -namespace ecstasy -{ - /// - /// @brief Base class of all registry resources. - /// - /// @author Andréas Leroux (andreas.leroux@epitech.eu) - /// @since 1.0.0 (2022-10-17) - /// - class ResourceBase -#ifdef ECSTASY_LOCKABLE_RESOURCES - : public thread::SharedRecursiveMutex -#endif - { - public: - /// @brief Default destructor. - virtual ~ResourceBase() = default; - }; // namespace ecstasy - - /// - /// @brief Resource class. - /// This class is templated to allow compatibility with LockableView. - /// - /// @tparam R Type of the resource. - /// - /// @author Andréas Leroux (andreas.leroux@epitech.eu) - /// @since 1.0.0 (2024-04-17) - /// - template - class Resource : public ResourceBase { - public: - /// - /// @brief Compatibility for LockableView. Using -> on a Resource or a LockableView will return the pointer to - /// the resource. - /// - /// @return R* Pointer to the resource. - /// - /// @author Andréas Leroux (andreas.leroux@epitech.eu) - /// @since 1.0.0 (2024-04-17) - /// - [[nodiscard]] R *operator->() noexcept - { - return dynamic_cast(this); - } - - /// @copydoc Resource::operator->() - [[nodiscard]] const R *operator->() const noexcept - { - return dynamic_cast(this); - } - }; -} // namespace ecstasy - -#endif /* !ECSTASY_RESOURCE_RESOURCE_HPP_ */ diff --git a/src/ecstasy/resources/entity/Entities.hpp b/src/ecstasy/resources/entity/Entities.hpp index 6891f30ff..4524279c0 100644 --- a/src/ecstasy/resources/entity/Entities.hpp +++ b/src/ecstasy/resources/entity/Entities.hpp @@ -16,7 +16,7 @@ #include #include "Entity.hpp" -#include "ecstasy/resources/Resource.hpp" +#include "ecstasy/resources/IResource.hpp" #include "util/BitSet.hpp" namespace ecstasy @@ -27,7 +27,7 @@ namespace ecstasy /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2022-10-18) /// - class Entities : public Resource { + class Entities : public IResource { public: /// /// @brief Entities builder to add multiple component to an entity on creation. diff --git a/src/ecstasy/resources/include.hpp b/src/ecstasy/resources/include.hpp index ef929c68b..9b1847047 100644 --- a/src/ecstasy/resources/include.hpp +++ b/src/ecstasy/resources/include.hpp @@ -12,8 +12,8 @@ #ifndef ECSTASY_RESOURCES_HPP_ #define ECSTASY_RESOURCES_HPP_ +#include "IResource.hpp" #include "ObjectWrapper.hpp" -#include "Resource.hpp" #include "entity/include.hpp" #endif /* !ECSTASY_RESOURCES_HPP_ */ diff --git a/src/ecstasy/thread/LockableView.hpp b/src/ecstasy/thread/LockableView.hpp index 8880a452e..65c7172c3 100644 --- a/src/ecstasy/thread/LockableView.hpp +++ b/src/ecstasy/thread/LockableView.hpp @@ -110,7 +110,7 @@ namespace ecstasy::thread /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2024-04-03) /// - L &operator*() + [[nodiscard]] L &operator*() noexcept { return _lockable; } @@ -123,7 +123,7 @@ namespace ecstasy::thread /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2024-04-03) /// - L *operator->() + [[nodiscard]] L *operator->() noexcept { return &_lockable; } @@ -139,11 +139,37 @@ namespace ecstasy::thread /// @author Andréas Leroux (andreas.leroux@epitech.eu) /// @since 1.0.0 (2024-04-03) /// - L *operator->() const + [[nodiscard]] L *operator->() const noexcept { return &_lockable; } + /// + /// @brief Access the internal lockable object. + /// + /// @return L& Reference to the internal lockable object. + /// + /// @author Andréas Leroux (andreas.leroux@epitech.eu) + /// @since 1.0.0 (2024-10-18) + /// + [[nodiscard]] L &get() noexcept + { + return _lockable; + } + + /// + /// @brief Access the internal lockable object. + /// + /// @return L& Reference to the internal lockable object. + /// + /// @author Andréas Leroux (andreas.leroux@epitech.eu) + /// @since 1.0.0 (2024-10-18) + /// + [[nodiscard]] L &get() const noexcept + { + return _lockable; + } + private: L &_lockable; }; diff --git a/tests/registry/tests_DeletionStack.cpp b/tests/registry/tests_DeletionStack.cpp index 7a26fc421..27029e110 100644 --- a/tests/registry/tests_DeletionStack.cpp +++ b/tests/registry/tests_DeletionStack.cpp @@ -25,10 +25,10 @@ TEST(DeletionStack, basic_cases) /// No deletion { - GTEST_ASSERT_EQ(registry.getEntities()->getMask(), util::BitSet("1111111111")); + GTEST_ASSERT_EQ(registry.getEntities().get().getMask(), util::BitSet("1111111111")); ecstasy::DeletionStack delStack(registry); } - GTEST_ASSERT_EQ(registry.getEntities()->getMask(), util::BitSet("1111111111")); + GTEST_ASSERT_EQ(registry.getEntities().get().getMask(), util::BitSet("1111111111")); { ecstasy::DeletionStack delStack(registry); @@ -38,11 +38,11 @@ TEST(DeletionStack, basic_cases) if (++i % 2 == 0) delStack.push(entity); /// Even if entity was marked for deletion it is still alive while the delStack isn't destroyed. - GTEST_ASSERT_TRUE(registry.getEntities()->isAlive(entity)); + GTEST_ASSERT_TRUE(registry.getEntities().get().isAlive(entity)); } - GTEST_ASSERT_EQ(registry.getEntities()->getMask(), util::BitSet("1111111111")); + GTEST_ASSERT_EQ(registry.getEntities().get().getMask(), util::BitSet("1111111111")); GTEST_ASSERT_EQ(delStack.size(), 5); } /// delStack deleted and so are the entities - GTEST_ASSERT_EQ(registry.getEntities()->getMask(), util::BitSet("0101010101")); + GTEST_ASSERT_EQ(registry.getEntities().get().getMask(), util::BitSet("0101010101")); } diff --git a/tests/registry/tests_Registry.cpp b/tests/registry/tests_Registry.cpp index 8e4beed42..0bb0b6d82 100644 --- a/tests/registry/tests_Registry.cpp +++ b/tests/registry/tests_Registry.cpp @@ -6,7 +6,7 @@ #include "ecstasy/registry/modifiers/Maybe.hpp" #include "ecstasy/registry/modifiers/Not.hpp" #include "ecstasy/registry/modifiers/Or.hpp" -#include "ecstasy/resources/Resource.hpp" +#include "ecstasy/resources/IResource.hpp" #include "ecstasy/resources/entity/RegistryEntity.hpp" #include "ecstasy/storages/MapStorage.hpp" #include "ecstasy/storages/MarkerStorage.hpp" @@ -56,7 +56,7 @@ class B : public ecstasy::ISystem { } }; -struct Counter : public ecstasy::Resource { +struct Counter : public ecstasy::IResource { int value; Counter(int initial = 0) @@ -206,8 +206,8 @@ TEST(Registry, resources) /// Add resource with an initial value of 5 and add one registry.addResource(5).count(); ASSERT_TRUE(registry.hasResource()); - EXPECT_EQ(registry.getResource()->value, 6); - EXPECT_EQ(cregistry.getResource()->value, 6); + EXPECT_EQ(registry.getResource().get().value, 6); + EXPECT_EQ(cregistry.getResource().get().value, 6); /// Try to add resource already present EXPECT_THROW(static_cast(registry.addResource()), std::logic_error); @@ -273,19 +273,19 @@ TEST(Registry, eraseEntity) for (int i = 0; i < 10; i++) registry.entityBuilder().with(1, 2).with(3, 4).build(); - GTEST_ASSERT_EQ(cregistry.getEntities()->getMask(), util::BitSet("1111111111")); + GTEST_ASSERT_EQ(cregistry.getEntities().get().getMask(), util::BitSet("1111111111")); GTEST_ASSERT_EQ(registry.getStorage().getMask(), util::BitSet("1111111111")); GTEST_ASSERT_EQ(registry.getStorage().getMask(), util::BitSet("1111111111")); GTEST_ASSERT_TRUE(registry.eraseEntity(registry.getEntity(1))); GTEST_ASSERT_FALSE(registry.eraseEntity(registry.getEntity(1))); GTEST_ASSERT_TRUE(registry.eraseEntity(registry.getEntity(5))); - GTEST_ASSERT_EQ(registry.getEntities()->getMask(), util::BitSet("1111011101")); + GTEST_ASSERT_EQ(registry.getEntities().get().getMask(), util::BitSet("1111011101")); GTEST_ASSERT_EQ(registry.getStorage().getMask(), util::BitSet("1111011101")); GTEST_ASSERT_EQ(registry.getStorage().getMask(), util::BitSet("1111011101")); - GTEST_ASSERT_TRUE(cregistry.getEntities()->isAlive(registry.getEntity(0))); - GTEST_ASSERT_FALSE(registry.getEntities()->isAlive(registry.getEntity(1))); - GTEST_ASSERT_FALSE(registry.getEntities()->isAlive(registry.getEntity(5))); + GTEST_ASSERT_TRUE(cregistry.getEntities().get().isAlive(registry.getEntity(0))); + GTEST_ASSERT_FALSE(registry.getEntities().get().isAlive(registry.getEntity(1))); + GTEST_ASSERT_FALSE(registry.getEntities().get().isAlive(registry.getEntity(5))); } TEST(Registry, eraseEntities) @@ -295,19 +295,19 @@ TEST(Registry, eraseEntities) for (int i = 0; i < 10; i++) registry.entityBuilder().with(1, 2).with(3, 4).build(); - GTEST_ASSERT_EQ(cregistry.getEntities()->getMask(), util::BitSet("1111111111")); + GTEST_ASSERT_EQ(cregistry.getEntities().get().getMask(), util::BitSet("1111111111")); GTEST_ASSERT_EQ(registry.getStorage().getMask(), util::BitSet("1111111111")); GTEST_ASSERT_EQ(registry.getStorage().getMask(), util::BitSet("1111111111")); ecstasy::Entity toDelete[] = {registry.getEntity(1), registry.getEntity(5)}; GTEST_ASSERT_EQ(registry.eraseEntities(std::span(toDelete)), 2); GTEST_ASSERT_EQ(registry.eraseEntities(std::span(toDelete)), 0); - GTEST_ASSERT_EQ(registry.getEntities()->getMask(), util::BitSet("1111011101")); + GTEST_ASSERT_EQ(registry.getEntities().get().getMask(), util::BitSet("1111011101")); GTEST_ASSERT_EQ(registry.getStorage().getMask(), util::BitSet("1111011101")); GTEST_ASSERT_EQ(registry.getStorage().getMask(), util::BitSet("1111011101")); - GTEST_ASSERT_TRUE(cregistry.getEntities()->isAlive(registry.getEntity(0))); - GTEST_ASSERT_FALSE(registry.getEntities()->isAlive(registry.getEntity(1))); - GTEST_ASSERT_FALSE(registry.getEntities()->isAlive(registry.getEntity(5))); + GTEST_ASSERT_TRUE(cregistry.getEntities().get().isAlive(registry.getEntity(0))); + GTEST_ASSERT_FALSE(registry.getEntities().get().isAlive(registry.getEntity(1))); + GTEST_ASSERT_FALSE(registry.getEntities().get().isAlive(registry.getEntity(5))); } TEST(Registry, EntityBuilder) @@ -361,8 +361,8 @@ TEST(Registry, EntityBuilder) /// Use Queryables with the builder ecstasy::Registry::EntityBuilder builder = registry.entityBuilder(); ecstasy::RegistryEntity e(builder.with().build(), builder.getRegistry()); - auto &resource = registry.getResource(); - EXPECT_EQ(&e.get().resource, &resource); + auto resource = registry.getResource(); + EXPECT_EQ(&e.get().resource, &resource.get()); } }