Cogs.Core
ResourceManager.h
1#pragma once
2
3#include "IResourceLoader.h"
4#include "IResourceManager.h"
5#include "ResourceManagerBase.h"
6#include "ResourceProxy.h"
7
8#include "../Engine.h"
9#include "../EntityDefinition.h"
10#include "../MemoryContext.h"
11
12#include "Foundation/Collections/Pool.h"
13#include "Foundation/Platform/Threads.h"
14
15#include <deque>
16
17namespace Cogs
18{
19 namespace Core
20 {
21 class Context;
22
23 constexpr ResourceTypes getResourceType(const ResourceBase *) { return ResourceTypes::Unknown; }
24 constexpr ResourceTypes getResourceType(const Asset *) { return ResourceTypes::Asset; }
25 constexpr ResourceTypes getResourceType(const Model *) { return ResourceTypes::Model; }
26 constexpr ResourceTypes getResourceType(const Texture *) { return ResourceTypes::Texture; }
27 constexpr ResourceTypes getResourceType(const Effect *) { return ResourceTypes::Effect; }
28 constexpr ResourceTypes getResourceType(const Material *) { return ResourceTypes::Material; }
29 constexpr ResourceTypes getResourceType(const MaterialInstance *) { return ResourceTypes::MaterialInstance; }
30 constexpr ResourceTypes getResourceType(const BufferResource *) { return ResourceTypes::Buffer; }
31 constexpr ResourceTypes getResourceType(const Mesh *) { return ResourceTypes::Mesh; }
32 constexpr ResourceTypes getResourceType(const Font *) { return ResourceTypes::Font; }
33 // GuiDocument omitted.
34
36 {
37 public:
38 virtual bool doesManage(DefaultValueType valueType) = 0;
39
40 virtual void readSource(Context* ctx, ResourceDefinition& definition, const void* jsonResource) = 0;
41
42 virtual void applyFieldValue(void* object, const Reflection::Field* field, const FieldValue& fieldValue) = 0;
43
44 };
46 {
47 public:
48 virtual void enable() = 0;
49
50 virtual BlueNoiseHandle getBlueNoiseHandle(bool stable) = 0;
51 };
52
53
74 template<typename ResourceType, typename LoadInfoType>
76 {
77 public:
80
83
86 {
87 SwapOperation() = default;
89 SwapOperation(const SwapOperation & other) = delete;
90 SwapOperation(SwapOperation && other) = default;
91
94
97 };
98
105 ResourceManagerBase(context),
106 resources(capacity, capacity, context->memory->resourceAllocator, MemBlockType::ResourceManager),
107 loadInfos(128, 128, context->memory->resourceAllocator, MemBlockType::ResourceManager)
108 {
109 resourceType = getResourceType(static_cast<const ResourceType*>(nullptr));
110 }
111
114 {
115 for (auto & loader : loaders) {
116 assert(loader);
117 delete loader;
118 loader = nullptr;
119 }
120 loaders.clear();
121 }
122
126 void clear() override
127 {
128 defaultResource = ResourceHandle();
129
130 ResourceManagerBase::clear();
131 }
132
136 void clearSwapping() override
137 {
138 LockGuard swapLock(swapMutex);
139
140 swapQueue.clear();
141 }
142
162 {
163 return ResourceHandle(createResource());
164 }
165
166 /*
167 * Releases the resource handle, e.g. remove access to the resource using the resource ID.
168 * The resource will not be deleted until all ResourceHandle instances are released.
169 * \param resourceId Resource handle to be released.
170 * \returns actual handle. Should only be used to check if the resourceId was found, e.g. valid handle returned.
171 */
172 ResourceHandle release(ResourceId resourceId)
173 {
174 return releaseInternal(resourceId);
175 }
176
177 ResourceHandle loadResource(LoadInfoType * loadInfo)
178 {
179 return loadResourceInternal(loadInfo);
180 }
181
182 protected:
183 ResourceType * createInternal() override
184 {
185 return resources.create();
186 }
187
188 void destroyInternal(ResourceBase * resource) override
189 {
190 resources.destroy(static_cast<ResourceType *>(resource));
191 }
192
193 private:
194 void destroyInternalLocked(ResourceBase * resource) override
195 {
196 resources.destroy(static_cast<ResourceType *>(resource));
197 }
198
199 protected:
200 void handleLoadInternal(ResourceLoadInfoBase * loadInfo) override
201 {
202 handleLoad(static_cast<LoadInfoType *>(loadInfo));
203 }
204
205 ActivationResult handleActivationInternal(ResourceHandleBase r, ResourceBase * resource) override
206 {
207 return handleActivation(r, static_cast<ResourceType *>(resource));
208 }
209
210 void handleDeletionInternal(ResourceBase * resource) override
211 {
212 handleDeletion(static_cast<ResourceType *>(resource));
213 }
214
215 void handleFailedLoadInternal(ResourceLoadInfoBase * loadInfo) override
216 {
217 handleFailedLoad(static_cast<LoadInfoType *>(loadInfo));
218 }
219
220 public:
236 {
237 auto handle = create();
238
239 return lock(handle);
240 }
241
253 {
254 auto proxy = create();
255 proxy->setProxy();
256 return ResourceProxy(*this, handle, proxy);
257 }
258
265 void unlockProxy(const ResourceHandle & handle, const ResourceHandle & proxy)
266 {
267 LockGuard swapLock(swapMutex);
268
269 swapQueue.emplace_back(handle, proxy);
270 }
271
281 {
282 return ResourceHandle(resource);
283 }
284
292 virtual void handleLoad(LoadInfoType * /*loadInfo*/) {}
293
301 virtual void handleFailedLoad(const LoadInfoType * /*loadInfo*/) {}
302
317 virtual ActivationResult handleActivation(ResourceHandle /*handle*/, ResourceType * /*resource*/) { return ActivationResult::Success; }
318
331 virtual void handleDeletion(ResourceType * /*resource*/) {}
332
342 ResourceType * get(const ResourceHandleBase & handle)
343 {
344 if (!HandleIsValid(handle) && !handle.get()) {
345 return static_cast<ResourceType*>(defaultResource.get());
346 }
347
348 return const_cast<ResourceType *>(static_cast<const ResourceType*>(handle.get()));
349 }
350
355 void processSwapping() override
356 {
357 LockGuard swapLock(swapMutex);
358
359 for (auto & swapResource : swapQueue) {
360 auto source = swapResource.source.resolve();
361 auto destination = swapResource.destinationHandle.resolve();
362
363 assert(source && "Source resource for swap cannot be null.");
364 assert(destination && "Destination resource for swap cannot be null.");
365
366 *destination = std::move(*swapResource.source.resolve());
367 destination->setLoaded();
368 destination->setChanged();
369 context->engine->setDirty();
370 }
371
372 swapQueue.clear();
373 }
374
382 ResourceHandle getHandle(const ResourceId id) const
383 {
384 return getResourceHandle(id);
385 }
386
398 {
399 loaders.push_back(loader);
400 }
401
402 void destroyLoadInfoInternal(ResourceLoadInfoBase * loadInfo) override
403 {
404 LockGuard lock(loadInfoMutex);
405
406 loadInfos.destroy(static_cast<LoadInfoType *>(loadInfo));
407 }
408
409 LoadInfoType * createLoadInfo()
410 {
411 LockGuard lock(loadInfoMutex);
412
413 return loadInfos.create();
414 }
415
416 protected:
426 {
427 for (auto loader : loaders) {
428 if (loader->canLoad(context, *loadInfo)) {
429 return loader;
430 }
431 }
432
433 return nullptr;
434 }
435
436 Mutex swapMutex;
437
439
440 std::vector<IResourceLoader<ResourceType, LoadInfoType> *> loaders;
441
442 std::deque<SwapOperation> swapQueue;
443
444 ResourceHandle defaultResource;
445
446 private:
447 Mutex loadInfoMutex;
449 };
450
451 }
452}
A Context instance contains all the services, systems and runtime components needed to use Cogs.
Definition: Context.h:83
std::unique_ptr< class Engine > engine
Engine instance.
Definition: Context.h:222
ResourceHandleBase releaseInternal(ResourceId resourceId)
Releases a resourceId -> ResourceHandle mapping.
ResourceHandleBase loadResourceInternal(ResourceLoadInfoBase *loadInfo)
Load a resource using the given loadInfo.
ResourceHandleBase getResourceHandle(ResourceId id) const
Get existing resource handle.
The generic resource manager provides a base implementation for specialized resource managers to buil...
ResourceHandle getHandle(const ResourceId id) const
Get a resource handle to the resource with the given id.
virtual void handleFailedLoad(const LoadInfoType *)
Handler for failed resource loads using the given loadInfo.
~ResourceManager() override
Destructs a resource manager, provided for destruction via base pointer.
ResourceManager(Context *context, Collections::ElementOffset capacity=1024)
Constructs a resource manager with the given context.
void clear() override
Clear the resource manager, cleaning up resources held by member handles.
ResourceHandle_t< ResourceType > ResourceHandle
Type of handle used to hold resources.
ResourceHandle create()
Create a new resource.
ResourceProxy lock(const ResourceHandle &handle)
Takes the handle given and returns a resource proxy to edit the contents of the held resource safely ...
virtual ActivationResult handleActivation(ResourceHandle, ResourceType *)
Handler for activation of resources.
ResourceType * get(const ResourceHandleBase &handle)
Resolve the given handle to a resource.
virtual void handleLoad(LoadInfoType *)
Handler for resource loading.
void clearSwapping() override
Clear the swap queue, ensuring indirect resource references are released.
ResourceHandle generateHandle(ResourceBase *resource)
Generate a handle to the given resource.
virtual void handleDeletion(ResourceType *)
Handler for deletion of resources.
IResourceLoader< ResourceType, LoadInfoType > * findLoader(const LoadInfoType *loadInfo)
Find a loader capable of loading the resource given by loadInfo.
void unlockProxy(const ResourceHandle &handle, const ResourceHandle &proxy)
Unlock the given resource proxy.
void processSwapping() override
Process queued swap operations, exchanging resource contents of the destination resources by those in...
ResourceProxy createLocked()
Creates a new resource, but returns a ResourceProxy for thread safe editing instead of a handle to th...
void registerLoader(IResourceLoader< ResourceType, LoadInfoType > *loader)
Register a resource loader capable of handling resources of the template type.
ResourceProxy< ResourceType, ResourceManager > ResourceProxy
Type of resource proxy objects, specialized on the type of resource.
Field definition describing a single data member of a data structure.
Definition: Field.h:68
uint16_t ElementOffset
Offset type used to index elements in resource pools.
Definition: PoolBase.h:13
ActivationResult
Defines results for resource activation.
Definition: ResourceBase.h:14
@ Success
Resource activated successfully.
bool HandleIsValid(const ResourceHandle_t< T > &handle)
Check if the given resource is valid, that is not equal to NoHandle or InvalidHandle.
ResourceTypes
Resource types.
Definition: ResourceBase.h:64
DefaultValueType
Defines value types for default values.
Contains all Cogs related functionality.
Definition: FieldSetter.h:23
Pool used to store elements of ElementType.
Definition: Pool.h:17
ElementType * create(ARGS &&... args)
Allocate and initialize a new element from the pool passing any arguments to the constructor of the n...
Definition: Pool.h:69
void destroy(ElementType *element)
Free and destroy the given element in the pool.
Definition: Pool.h:82
Defines a value to apply to a field.
Base class for engine resources.
Definition: ResourceBase.h:107
Resource handle base class handling reference counting of resources derived from ResourceBase.
Defines a swap operation replacing the contents of a resource.
ResourceHandle destinationHandle
Handle to the destination resource to replace contents of.
ResourceHandle source
Source resource to move data from.