CeresEngine 0.2.0
A game development framework
Loading...
Searching...
No Matches
ResourceHandle.hpp
Go to the documentation of this file.
1//
2// CeresEngine - A game development framework
3//
4// Created by Rogiel Sulzbach.
5// Copyright (c) 2018-2022 Rogiel Sulzbach. All rights reserved.
6//
7
8#pragma once
9
10#include "Forward.hpp"
11
13
18
19namespace CeresEngine {
20
21 class AbstractResourceHandle;
22
24 friend class ResourceManager;
26 template<typename T> friend class ResourceHandle;
27 template<typename T> friend class WeakResourceHandle;
28
29 private:
32
35 const UUID mUUID;
36
41
46
51
54
57
58 public:
63 explicit ResourceHandleData(ResourceManager& manager, const UUID& uuid, ResourcePtr&& resource = nullptr)
64 : mResourceManager(&manager), mUUID(uuid), mResource(std::move(resource)) {}
65
69 explicit ResourceHandleData(const UUID& uuid, ResourcePtr&& resource = nullptr) : mUUID(uuid), mResource(std::move(resource)) {}
70
74
75 public:
77 [[nodiscard]] const UUID& getUUID() const noexcept { return mUUID; }
78
81
84
85 private: // Interface for ResourceHandle/WeakResouceHandle
90
95
99 void weakRetain();
100
105
106 private: // Interface for ResourceManager
109 void setResource(ResourcePtr&& resource);
110
115 };
116
119 protected:
121
122 public:
125 explicit AbstractResourceHandle(SPtr<Resource> resource) noexcept;
126
127 public:
130 static const UUID nullUUID;
131 return mData != nullptr ? mData->getUUID() : nullUUID;
132 }
133
135 [[nodiscard]] bool isValid() const noexcept { return mData != nullptr; }
136
139
141 [[nodiscard]] bool isLoaded() const noexcept { return mData != nullptr && mData->mResource != nullptr; }
142
144 [[nodiscard]] explicit operator bool() const noexcept { return isLoaded(); }
145
147 void reset() { set(nullptr); }
148
149 protected:
153 void set(ResourceHandleData* const data) noexcept {
154 if(mData != nullptr) {
156 }
157
158 mData = data;
159
160 if(mData != nullptr) {
162 }
163 }
164 };
165
166 template<typename T> class ResourceHandle final : public AbstractResourceHandle {
167 friend class ResourceManager;
169 friend class ResourceHandleData;
170 template<typename> friend class ResourceHandle;
171 template<typename> friend class WeakResourceHandle;
172
173 public:
175
177 ResourceHandle& operator=(std::nullptr_t) {
178 set(nullptr);
179 return *this;
180 }
181
182 ResourceHandle(const ResourceHandle& other) { set(other.mData); }
184 set(other.mData);
185 return *this;
186 }
187
188 template<typename U>
189 requires(std::is_convertible_v<U*, T*>)
190 CE_EXPLICIT(false) ResourceHandle(const ResourceHandle<U>& other) noexcept {
191 set(other.mData);
192 }
193
194 template<typename U>
195 requires(std::is_convertible_v<U*, T*>)
196 ResourceHandle& operator=(const ResourceHandle<U>& other) {
197 set(other.mData);
198 return *this;
199 }
200
201 ResourceHandle(ResourceHandle&& other) noexcept { mData = std::exchange(other.mData, nullptr); }
203 set(nullptr);
204 mData = std::exchange(other.mData, nullptr);
205 return *this;
206 }
207
208 template<typename U>
209 requires(std::is_convertible_v<U*, T*>)
211 mData = std::exchange(other.mData, nullptr);
212 }
213
214 template<typename U>
215 requires(std::is_convertible_v<U*, T*>)
216 ResourceHandle& operator=(ResourceHandle<U>&& other) {
217 set(nullptr);
218 mData = std::exchange(other.mData, nullptr);
219 return *this;
220 }
221
222 explicit ResourceHandle(SPtr<T> resource) noexcept : AbstractResourceHandle(std::move(resource)) {}
223
225
226 private:
227 explicit ResourceHandle(ResourceHandleData* data) { set(data); }
228
229 public:
231 [[nodiscard]] T* get() const noexcept { return static_cast<T*>(mData != nullptr ? mData->getResource() : nullptr); }
232
234 [[nodiscard]] SPtr<T> getPointer() const noexcept { return mData != nullptr ? std::static_pointer_cast<T>(mData->getResourcePointer()) : nullptr; }
235
238 CE_ASSERT(mData != nullptr);
239 return get();
240 }
241
244 CE_ASSERT(mData != nullptr);
245 Resource* const resource = mData->getResource();
246 CE_ASSERT(resource != nullptr);
247 return *static_cast<T*>(resource);
248 }
249
252
253 public: // Resource load events
258 template<typename Func> [[nodiscard]] EventConnection didLoadResource(Func&& func) {
259 return mData->didLoadResource.connect(
260 [func = std::forward<Func>(func)](const HResource& handle) mutable { std::move(func)(static_resource_cast<T>(handle)); });
261 }
262
263 template<typename Func> [[nodiscard]] EventConnection didUnloadResource(Func&& func) {
264 return mData->didUnloadResource.connect(
265 [func = std::forward<Func>(func)](const HResource& handle) mutable { std::move(func)(static_resource_cast<T>(handle)); });
266 }
267
268 public:
275 template<typename U1, typename U2>
276 friend bool operator==(const ResourceHandle<U1>& lhs, const ResourceHandle<U2>& rhs) noexcept;
277
284 template<typename U1, typename U2>
285 friend bool operator!=(const ResourceHandle<U1>& lhs, const ResourceHandle<U2>& rhs) noexcept;
286
291 template<typename U> friend bool operator==(const ResourceHandle<U>& lhs, std::nullptr_t) noexcept;
292
294 template<typename U> friend bool operator==(std::nullptr_t, const ResourceHandle<U>& rhs) noexcept;
295
300 template<typename U> friend bool operator!=(const ResourceHandle<U>& lhs, std::nullptr_t) noexcept;
301
303 template<typename U> friend bool operator!=(std::nullptr_t, const ResourceHandle<U>& rhs) noexcept;
304
305 public:
306 template<typename U, typename V> friend ResourceHandle<U> static_resource_cast(const ResourceHandle<V>& handle);
307 template<typename U, typename V> friend ResourceHandle<U> static_resource_cast(ResourceHandle<V>&& handle);
308 };
309
310 template<typename U1, typename U2>
311 inline bool operator==(const ResourceHandle<U1>& lhs, const ResourceHandle<U2>& rhs) noexcept {
312 return lhs.mData == rhs.mData;
313 }
314
315 template<typename U1, typename U2> inline bool operator!=(const ResourceHandle<U1>& lhs, const ResourceHandle<U2>& rhs) noexcept {
316 return lhs.mData != rhs.mData;
317 }
318
319 template<typename U> bool operator==(const ResourceHandle<U>& lhs, std::nullptr_t) noexcept { return lhs.mData == nullptr; }
320 template<typename U> bool operator==(std::nullptr_t, const ResourceHandle<U>& rhs) noexcept { return rhs == nullptr; }
321 template<typename U> bool operator!=(const ResourceHandle<U>& lhs, std::nullptr_t) noexcept { return lhs.mData != nullptr; }
322 template<typename U> bool operator!=(std::nullptr_t, const ResourceHandle<U>& rhs) noexcept { return rhs != nullptr; }
323
324 // ---------------------------------------------------------------------------------------------
325
326 template<typename U, typename V> ResourceHandle<U> static_resource_cast(const ResourceHandle<V>& handle) { return ResourceHandle<U>(handle.mData); }
327 template<typename U, typename V> ResourceHandle<U> static_resource_cast(ResourceHandle<V>&& handle) { return ResourceHandle<U>(std::move(handle.mData)); }
328
329 // ---------------------------------------------------------------------------------------------
330
331 template<typename T> Async<ResourceHandle<T>> ResourceHandle<T>::load() const {
332 return AbstractResourceHandle::load() | [](const HResource& resource) {
333 return static_resource_cast<T>(resource);
334 };
335 }
336
337 // ---------------------------------------------------------------------------------------------
338
339 template<typename T> class WeakResourceHandle final {
340 friend class ResourceManager;
341
342 private:
344
345 public:
347
349 WeakResourceHandle& operator=(std::nullptr_t) {
350 set(nullptr);
351 return *this;
352 }
353
356 set(other.mData);
357 return *this;
358 }
359
360 template<typename U>
361 requires(std::is_convertible_v<U*, T*>)
363 set(other.mData);
364 }
365
366 template<typename U>
367 requires(std::is_convertible_v<U*, T*>)
368 WeakResourceHandle& operator=(const WeakResourceHandle<U>& other) {
369 set(other.mData);
370 return *this;
371 }
372
373 WeakResourceHandle(WeakResourceHandle&& other) noexcept { mData = std::exchange(other.mData, nullptr); }
375 set(nullptr);
376 mData = std::exchange(other.mData, nullptr);
377 return *this;
378 }
379
380 template<typename U>
381 requires(std::is_convertible_v<U*, T*>)
383 mData = std::exchange(other.mData, nullptr);
384 }
385
386 template<typename U>
387 requires(std::is_convertible_v<U*, T*>)
389 set(nullptr);
390 mData = std::exchange(other.mData, nullptr);
391 return *this;
392 }
393
394 template<typename U>
395 requires(std::is_convertible_v<U*, T*>)
396 CE_EXPLICIT(false) WeakResourceHandle(const ResourceHandle<U>& other) noexcept {
397 set(other.mData);
398 }
399
400 template<typename U>
401 requires(std::is_convertible_v<U*, T*>)
402 WeakResourceHandle& operator=(const ResourceHandle<U>& other) {
403 set(other.mData);
404 return *this;
405 }
406
408
409 private:
410 explicit WeakResourceHandle(ResourceHandleData* data) { set(data); }
411
412 public:
414
415 public:
418 static UUID empty;
419 if(mData == nullptr) {
420 return empty;
421 }
422
423 return mData->getUUID();
424 }
425
426 private:
430 void set(ResourceHandleData* data) noexcept {
431 if(mData != nullptr) {
433 }
434
435 mData = data;
436
437 if(mData != nullptr) {
438 mData->weakRetain();
439 }
440 }
441
442 public:
443 template<typename U, typename V> friend WeakResourceHandle<U> static_resource_cast(const WeakResourceHandle<V>& handle);
444 template<typename U, typename V> friend WeakResourceHandle<U> static_resource_cast(WeakResourceHandle<V>&& handle);
445 };
446
447 template<typename U, typename V> WeakResourceHandle<U> static_resource_cast(const WeakResourceHandle<V>& handle) {
448 return WeakResourceHandle<U>(handle.mData);
449 }
450
451 template<typename U, typename V> WeakResourceHandle<U> static_resource_cast(WeakResourceHandle<V>&& handle) {
452 return WeakResourceHandle<U>(std::move(handle.mData));
453 }
454
455} // namespace CeresEngine
456
457template<typename T> struct std::hash<CeresEngine::ResourceHandle<T>> final {
458 using HashedType = CeresEngine::ResourceHandle<T>;
459 size_t operator()(const HashedType& type) const {
460 using CeresEngine::hash;
461 return hash(type.getUUID());
462 }
463};
#define CE_ASSERT(...)
Definition Macros.hpp:323
#define CE_EXPLICIT(EXPR)
Definition Macros.hpp:413
Base class for weak and strong resource handle implementation.
Definition ResourceHandle.hpp:118
bool isLoaded() const noexcept
Checks if the resource handle is valid and loaded.
Definition ResourceHandle.hpp:141
AbstractResourceHandle(ResourceHandleData *data)
Definition ResourceHandle.hpp:124
AbstractResourceHandle(SPtr< Resource > resource) noexcept
bool isValid() const noexcept
Checks if the resource handle is valid.
Definition ResourceHandle.hpp:135
ResourceHandleData * mData
Definition ResourceHandle.hpp:120
const UUID & getUUID() const noexcept
Definition ResourceHandle.hpp:129
void set(ResourceHandleData *const data) noexcept
Changes the internal resource handle data object of the handle.
Definition ResourceHandle.hpp:153
Async< HResource > load() const
Loads the resource, if not loaded.
void reset()
Resets the resource handle to the default state.
Definition ResourceHandle.hpp:147
Scoped connection class.
Definition Event.hpp:104
A class that implements a simple interface for reference counting.
Definition SmartPtr.hpp:82
Definition ResourceHandle.hpp:23
~ResourceHandleData()
Destroys the resource handle data and notifies the manager that it is being destroyed.
Event< void(const HResource &)> didUnloadResource
An event fired whenever the resource is unloaded.
Definition ResourceHandle.hpp:56
const UUID mUUID
The resource UUID the handle is representing.
Definition ResourceHandle.hpp:35
void notifyStrongRelease()
Notifies the ResourceManager that all strong ResourceHandles have been destroyed and the manager can ...
ResourcePtr mResource
The resource being managed by the resource handle, if any.
Definition ResourceHandle.hpp:40
Event< void(const HResource &)> didLoadResource
An event fired whenever the resource is loaded.
Definition ResourceHandle.hpp:53
void strongRetain()
Retains the strong resource count.
void setResource(ResourcePtr &&resource)
Changes the resource instance.
Resource * getResource() const noexcept
The resource being managed by the resource handle, if any.
Definition ResourceHandle.hpp:80
void weakRelease()
Releases the weak resource count.
ResourceHandleData(ResourceManager &manager, const UUID &uuid, ResourcePtr &&resource=nullptr)
Creates a new resource handle data.
Definition ResourceHandle.hpp:63
RefCounter mReferenceCounter
A reference counter that counts the number of total references (strong + weak) to the resource.
Definition ResourceHandle.hpp:45
RefCounter mStrongReferenceCounter
A reference counter that counts the number of strong references to the resource.
Definition ResourceHandle.hpp:50
const ResourcePtr & getResourcePointer() const noexcept
The resource being managed by the resource handle, if any.
Definition ResourceHandle.hpp:83
ResourceManager * mResourceManager
The resource manager that the handle belongs to.
Definition ResourceHandle.hpp:31
void weakRetain()
Retains the weak resource count.
const UUID & getUUID() const noexcept
The resource UUID the handle is representing.
Definition ResourceHandle.hpp:77
void strongRelease()
Releases the strong resource count.
ResourceHandleData(const UUID &uuid, ResourcePtr &&resource=nullptr)
Creates a new resource handle data.
Definition ResourceHandle.hpp:69
Definition ResourceHandle.hpp:166
ResourceHandle & operator=(ResourceHandle &&other) noexcept
Definition ResourceHandle.hpp:202
ResourceHandle(const ResourceHandle< U > &other) noexcept
Definition ResourceHandle.hpp:190
ResourceHandle(const ResourceHandle &other)
Definition ResourceHandle.hpp:182
friend bool operator!=(std::nullptr_t, const ResourceHandle< U > &rhs) noexcept
Checks if both references not represent the same handle.
Definition ResourceHandle.hpp:322
friend bool operator!=(const ResourceHandle< U1 > &lhs, const ResourceHandle< U2 > &rhs) noexcept
Checks if both references not represent the same handle.
Definition ResourceHandle.hpp:315
ResourceHandle() noexcept=default
friend bool operator==(const ResourceHandle< U > &lhs, std::nullptr_t) noexcept
Checks if the reference lhs is nullptr.
Definition ResourceHandle.hpp:319
T & operator*() const noexcept
Definition ResourceHandle.hpp:243
T * get() const noexcept
Definition ResourceHandle.hpp:231
ResourceHandle & operator=(std::nullptr_t)
Definition ResourceHandle.hpp:177
Async< ResourceHandle< T > > load() const
Loads the resource, if not loaded.
Definition ResourceHandle.hpp:331
friend bool operator==(std::nullptr_t, const ResourceHandle< U > &rhs) noexcept
Checks if both references represent the same handle.
Definition ResourceHandle.hpp:320
SPtr< T > getPointer() const noexcept
Definition ResourceHandle.hpp:234
EventConnection didUnloadResource(Func &&func)
Definition ResourceHandle.hpp:263
ResourceHandle(SPtr< T > resource) noexcept
Definition ResourceHandle.hpp:222
T * operator->() const noexcept
Definition ResourceHandle.hpp:237
ResourceHandle & operator=(const ResourceHandle &other)
Definition ResourceHandle.hpp:183
ResourceHandle(ResourceHandle &&other) noexcept
Definition ResourceHandle.hpp:201
friend bool operator==(const ResourceHandle< U1 > &lhs, const ResourceHandle< U2 > &rhs) noexcept
Checks if both references represent the same handle.
Definition ResourceHandle.hpp:311
friend class AbstractResourceHandle
Definition ResourceHandle.hpp:168
EventConnection didLoadResource(Func &&func)
Attaches a new event that will called whenever the.
Definition ResourceHandle.hpp:258
friend bool operator!=(const ResourceHandle< U > &lhs, std::nullptr_t) noexcept
Checks if the reference lhs is not nullptr.
Definition ResourceHandle.hpp:321
ResourceHandle(ResourceHandle< U > &&other) noexcept
Definition ResourceHandle.hpp:210
ResourceHandle(ResourceHandleData *data)
Definition ResourceHandle.hpp:227
friend ResourceHandle< U > static_resource_cast(const ResourceHandle< V > &handle)
Definition ResourceHandle.hpp:326
~ResourceHandle() noexcept
Definition ResourceHandle.hpp:224
friend ResourceHandle< U > static_resource_cast(ResourceHandle< V > &&handle)
Definition ResourceHandle.hpp:327
A base class that all resources must extend from.
Definition Resource.hpp:186
The ResourceManager is the main class responsible for managing and handling all resources in the engi...
Definition ResourceManager.hpp:47
Base template for the event class.
Definition Event.hpp:27
Definition ResourceHandle.hpp:339
friend WeakResourceHandle< U > static_resource_cast(WeakResourceHandle< V > &&handle)
Definition ResourceHandle.hpp:451
WeakResourceHandle(const ResourceHandle< U > &other) noexcept
Definition ResourceHandle.hpp:396
WeakResourceHandle(ResourceHandleData *data)
Definition ResourceHandle.hpp:410
WeakResourceHandle() noexcept=default
WeakResourceHandle & operator=(const WeakResourceHandle &other)
Definition ResourceHandle.hpp:355
WeakResourceHandle & operator=(std::nullptr_t)
Definition ResourceHandle.hpp:349
void set(ResourceHandleData *data) noexcept
Changes the internal resource handle data object of the handle.
Definition ResourceHandle.hpp:430
WeakResourceHandle(const WeakResourceHandle &other)
Definition ResourceHandle.hpp:354
WeakResourceHandle(const WeakResourceHandle< U > &other) noexcept
Definition ResourceHandle.hpp:362
ResourceHandle< T > lock() const noexcept
Definition ResourceHandle.hpp:413
WeakResourceHandle(WeakResourceHandle< U > &&other) noexcept
Definition ResourceHandle.hpp:382
WeakResourceHandle & operator=(WeakResourceHandle &&other) noexcept
Definition ResourceHandle.hpp:374
const UUID & getUUID() const noexcept
Definition ResourceHandle.hpp:417
~WeakResourceHandle() noexcept
Definition ResourceHandle.hpp:407
ResourceHandleData * mData
Definition ResourceHandle.hpp:343
WeakResourceHandle(WeakResourceHandle &&other) noexcept
Definition ResourceHandle.hpp:373
friend WeakResourceHandle< U > static_resource_cast(const WeakResourceHandle< V > &handle)
Definition ResourceHandle.hpp:447
Definition Application.hpp:19
std::shared_ptr< T > SPtr
SPtr is a smart pointer that retains shared ownership of an object through a pointer.
Definition SmartPtr.hpp:37
cti::continuable< Args... > Async
Defines a non-copyable continuation type which uses the function2 backend for type erasure.
Definition Async.hpp:22
auto move(Vector3 position)
Moves a entity to the given position.
Definition Helpers.hpp:22
bool operator!=(const ShortAllocator< T, N, A1 > &x, const ShortAllocator< U, M, A2 > &y) noexcept
Definition Allocator.hpp:416
SPtr< Resource > ResourcePtr
Definition Forward.hpp:47
bool operator==(const ShortAllocator< T, N, A1 > &x, const ShortAllocator< U, M, A2 > &y) noexcept
Definition Allocator.hpp:411
ResourceHandle< U > static_resource_cast(const ResourceHandle< V > &handle)
Definition ResourceHandle.hpp:326
constexpr size_t hash(const T &v)
Generates a hash for the provided type.
Definition Hash.hpp:25
Definition Span.hpp:668
Represents a universally unique identifier (UUID).
Definition UUID.hpp:27