Helios Engine 0.1.0
A modular ECS based data-oriented C++23 game engine
 
Loading...
Searching...
No Matches
resources_manager.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <helios/core_pch.hpp>
4
8
9#include <concepts>
10#include <cstddef>
11#include <memory>
12#include <type_traits>
13#include <unordered_map>
14
15namespace helios::ecs::details {
16
17/**
18 * @brief Base class for type-erased resource storage.
19 */
21public:
22 virtual ~ResourceStorageBase() = default;
23};
24
25/**
26 * @brief Type-specific resource storage.
27 * @tparam T Resource type
28 */
29template <ResourceTrait T>
31public:
32 template <typename... Args>
33 requires std::constructible_from<T, Args...>
34 explicit(sizeof...(Args) == 1) ResourceStorage(Args&&... args) noexcept(std::is_nothrow_constructible_v<T, Args...>)
35 : resource_(std::forward<Args>(args)...) {}
36
37 ResourceStorage(const ResourceStorage&) noexcept(std::is_nothrow_copy_constructible_v<T>)
38 requires std::copy_constructible<T>
39 = default;
40
43 = default;
44
46
49 = default;
50
53 = default;
54
55 [[nodiscard]] T& Get() noexcept { return resource_; }
56 [[nodiscard]] const T& Get() const noexcept { return resource_; }
57
58private:
59 T resource_;
60};
61
62/**
63 * @brief Resource container for World.
64 * @details Manages resources with thread-safe access using Boost's concurrent_node_map.
65 * @note Not thread-safe.
66 */
67class Resources {
68public:
69 Resources() = default;
70 Resources(const Resources&) = delete;
73
76
77 /**
78 * @brief Clears all resources.
79 */
80 void Clear() { resources_.clear(); }
81
82 /**
83 * @brief Inserts a new resource.
84 * @details Replaces existing resource if present.
85 * @tparam T Resource type
86 * @param resource Resource to insert
87 */
88 template <ResourceTrait T>
89 void Insert(T&& resource);
90
91 /**
92 * @brief Tries to insert a resource if not present.
93 * @tparam T Resource type
94 * @param resource Resource to insert
95 * @return True if inserted, false if resource already exists
96 */
97 template <ResourceTrait T>
98 bool TryInsert(T&& resource);
99
100 /**
101 * @brief Emplaces a new resource in-place.
102 * @details Constructs resource directly in storage.
103 * @tparam T Resource type
104 * @tparam Args Constructor argument types
105 * @param args Arguments to forward to resource constructor
106 */
107 template <ResourceTrait T, typename... Args>
108 requires std::constructible_from<T, Args...>
109 void Emplace(Args&&... args);
110
111 /**
112 * @brief Tries to emplace a resource if not present.
113 * @tparam T Resource type
114 * @tparam Args Constructor argument types
115 * @param args Arguments to forward to resource constructor
116 * @return True if emplaced, false if resource already exists
117 */
118 template <ResourceTrait T, typename... Args>
119 requires std::constructible_from<T, Args...>
120 bool TryEmplace(Args&&... args);
121
122 /**
123 * @brief Removes a resource.
124 * @warning Triggers assertion if resource doesn't exist.
125 * @tparam T Resource type
126 */
127 template <ResourceTrait T>
128 void Remove();
129
130 /**
131 * @brief Tries to remove a resource.
132 * @tparam T Resource type
133 * @return True if removed, false if resource didn't exist
134 */
135 template <ResourceTrait T>
136 bool TryRemove();
137
138 /**
139 * @brief Gets mutable reference to a resource.
140 * Triggers assertion if resource doesn't exist.
141 * @tparam T Resource type
142 * @return Mutable reference to resource
143 */
144 template <ResourceTrait T>
145 [[nodiscard]] T& Get();
146
147 /**
148 * @brief Gets const reference to a resource.
149 * Triggers assertion if resource doesn't exist.
150 * @tparam T Resource type
151 * @return Const reference to resource
152 */
153 template <ResourceTrait T>
154 [[nodiscard]] const T& Get() const;
155
156 /**
157 * @brief Tries to get mutable pointer to a resource.
158 * @tparam T Resource type
159 * @return Pointer to resource, or nullptr if not found
160 */
161 template <ResourceTrait T>
162 [[nodiscard]] T* TryGet();
163
164 /**
165 * @brief Tries to get const pointer to a resource.
166 * @tparam T Resource type
167 * @return Const pointer to resource, or nullptr if not found
168 */
169 template <ResourceTrait T>
170 [[nodiscard]] const T* TryGet() const;
171
172 /**
173 * @brief Checks if a resource exists.
174 * @tparam T Resource type
175 * @return True if resource exists, false otherwise
176 */
177 template <ResourceTrait T>
178 [[nodiscard]] bool Has() const;
179
180 /**
181 * @brief Gets the number of stored resources.
182 * @return Resource count
183 */
184 [[nodiscard]] size_t Count() const { return resources_.size(); }
185
186private:
187 /// Concurrent map of resource type IDs to their storage
188 std::unordered_map<ResourceTypeId, std::unique_ptr<ResourceStorageBase>> resources_;
189};
190
191template <ResourceTrait T>
193 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
194 auto storage = std::make_unique<ResourceStorage<T>>(std::forward<T>(resource));
195 resources_.insert_or_assign(type_id, std::move(storage));
196}
197
198template <ResourceTrait T>
200 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
201 auto storage = std::make_unique<ResourceStorage<T>>(std::forward<T>(resource));
202 return resources_.try_emplace(type_id, std::move(storage)).second;
203}
204
205template <ResourceTrait T, typename... Args>
206 requires std::constructible_from<T, Args...>
207inline void Resources::Emplace(Args&&... args) {
208 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
209 auto storage = std::make_unique<ResourceStorage<T>>(std::forward<Args>(args)...);
210 resources_.insert_or_assign(type_id, std::move(storage));
211}
212
213template <ResourceTrait T, typename... Args>
214 requires std::constructible_from<T, Args...>
215inline bool Resources::TryEmplace(Args&&... args) {
216 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
217 auto storage = std::make_unique<ResourceStorage<T>>(std::forward<Args>(args)...);
218 return resources_.try_emplace(type_id, std::move(storage)).second;
219}
220
221template <ResourceTrait T>
222inline void Resources::Remove() {
223 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
224 const size_t erased = resources_.erase(type_id);
225 HELIOS_ASSERT(erased > 0, "Failed to remove resource '{}': Resource does not exist!", ResourceNameOf<T>());
226}
227
228template <ResourceTrait T>
229inline bool Resources::TryRemove() {
230 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
231 return resources_.erase(type_id) > 0;
232}
233
234template <ResourceTrait T>
235inline T& Resources::Get() {
236 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
237 const auto it = resources_.find(type_id);
238 HELIOS_ASSERT(it != resources_.end(), "Failed to get resource '{}': Resource does not exist!", ResourceNameOf<T>());
239 return static_cast<ResourceStorage<T>&>(*it->second).Get();
240}
241
242template <ResourceTrait T>
243inline const T& Resources::Get() const {
244 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
245 const auto it = resources_.find(type_id);
246 HELIOS_ASSERT(it != resources_.end(), "Failed to get resource '{}': Resource does not exist!", ResourceNameOf<T>());
247 return static_cast<const ResourceStorage<T>&>(*it->second).Get();
248}
249
250template <ResourceTrait T>
251inline T* Resources::TryGet() {
252 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
253 const auto it = resources_.find(type_id);
254 if (it == resources_.end()) {
255 return nullptr;
256 }
257 return &static_cast<ResourceStorage<T>&>(*it->second).Get();
258}
259
260template <ResourceTrait T>
261inline const T* Resources::TryGet() const {
262 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
263 const auto it = resources_.find(type_id);
264 if (it == resources_.end()) {
265 return nullptr;
266 }
267 return &static_cast<const ResourceStorage<T>&>(*it->second).Get();
268}
269
270template <ResourceTrait T>
271inline bool Resources::Has() const {
272 constexpr ResourceTypeId type_id = ResourceTypeIdOf<T>();
273 return resources_.contains(type_id);
274}
275
276} // namespace helios::ecs::details
#define HELIOS_ASSERT(condition,...)
Assertion macro that aborts execution in debug builds.
Definition assert.hpp:140
Base class for type-erased resource storage.
Type-specific resource storage.
ResourceStorage(const ResourceStorage &) noexcept(std::is_nothrow_copy_constructible_v< T >)=default
ResourceStorage(ResourceStorage &&) noexcept(std::is_nothrow_move_constructible_v< T >)=default
Resource container for World.
bool Has() const
Checks if a resource exists.
void Insert(T &&resource)
Inserts a new resource.
bool TryRemove()
Tries to remove a resource.
size_t Count() const
Gets the number of stored resources.
bool TryInsert(T &&resource)
Tries to insert a resource if not present.
void Remove()
Removes a resource.
T * TryGet()
Tries to get mutable pointer to a resource.
void Clear()
Clears all resources.
Resources(const Resources &)=delete
bool TryEmplace(Args &&... args)
Tries to emplace a resource if not present.
Resources(Resources &&) noexcept=default
T & Get()
Gets mutable reference to a resource. Triggers assertion if resource doesn't exist.
void Emplace(Args &&... args)
Emplaces a new resource in-place.
Concept for valid resource types.
Definition resource.hpp:21
size_t ResourceTypeId
Type ID for resources.
Definition resource.hpp:53
BasicQuery< World, Allocator, Components... > Query
Type alias for query with mutable world access.
Definition query.hpp:2481
STL namespace.