Coverage Report

Created: 2025-11-04 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/include/OgreResourceManager.h
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
    (Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#ifndef _ResourceManager_H__
29
#define _ResourceManager_H__
30
31
#include "OgrePrerequisites.h"
32
33
#include "OgreResource.h"
34
#include "OgreResourceGroupManager.h"
35
#include "OgreCommon.h"
36
#include "OgreStringVector.h"
37
#include "OgreScriptLoader.h"
38
#include "OgreHeaderPrefix.h"
39
40
namespace Ogre {
41
42
    /** Template class describing a simple pool of items.
43
     */
44
    template <typename T>
45
    class Pool
46
    {
47
    protected:
48
        typedef typename std::list<T> ItemList;
49
        ItemList mItems;
50
        OGRE_AUTO_MUTEX;
51
    public:
52
        Pool() {}
53
        virtual ~Pool() {}
54
55
        /** Get the next item from the pool.
56
         @return pair indicating whether there was a free item, and the item if so
57
         */
58
        virtual std::pair<bool, T> removeItem()
59
        {
60
            OGRE_LOCK_AUTO_MUTEX;
61
            std::pair<bool, T> ret;
62
            if (mItems.empty())
63
            {
64
                ret.first = false;
65
            }
66
            else
67
            {
68
                ret.first = true;
69
                ret.second = mItems.front();
70
                mItems.pop_front();
71
            }
72
            return ret;
73
        }
74
75
        /** Add a new item to the pool.
76
         */
77
        virtual void addItem(const T& i)
78
        {
79
            OGRE_LOCK_AUTO_MUTEX;
80
            mItems.push_front(i);
81
        }
82
        /// Clear the pool
83
        virtual void clear()
84
        {
85
            OGRE_LOCK_AUTO_MUTEX;
86
            mItems.clear();
87
        }
88
    };
89
90
    /** \addtogroup Core
91
    *  @{
92
    */
93
    /** \addtogroup Resources
94
    *  @{
95
    */
96
    /** Defines a generic resource handler.
97
    @see @ref Resource-Management
98
    @note
99
        If OGRE_THREAD_SUPPORT is 1, this class is thread-safe.
100
    */
101
    class _OgreExport ResourceManager : public ScriptLoader, public ResourceAlloc
102
    {
103
    public:
104
        OGRE_AUTO_MUTEX; // public to allow external locking
105
        ResourceManager();
106
        virtual ~ResourceManager();
107
108
        /** Creates a new blank resource, but does not immediately load it.
109
        @param name The unique name of the %Resource
110
        @param group The name of the resource group to attach this new resource to
111
        @param isManual Is this resource manually loaded? If so, you should really
112
            populate the loader parameter in order that the load process
113
            can call the loader back when loading is required. 
114
        @param loader Pointer to a ManualLoader implementation which will be called
115
            when the Resource wishes to load (should be supplied if you set
116
            isManual to true). You can in fact leave this parameter null 
117
            if you wish, but the Resource will never be able to reload if 
118
            anything ever causes it to unload. Therefore provision of a proper
119
            ManualLoader instance is strongly recommended.
120
        @param createParams If any parameters are required to create an instance,
121
            they should be supplied here as name / value pairs
122
        */
123
        ResourcePtr createResource(const String& name, const String& group,
124
            bool isManual = false, ManualResourceLoader* loader = 0, 
125
            const NameValuePairList* createParams = 0);
126
127
        typedef std::pair<ResourcePtr, bool> ResourceCreateOrRetrieveResult;
128
        /** Create a new resource, or retrieve an existing one with the same
129
            name if it already exists.
130
131
            This method performs the same task as calling getByName() followed
132
            by create() if that returns null. The advantage is that it does it
133
            in one call so there are no race conditions if using multiple
134
            threads that could cause getByName() to return null, but create() to
135
            fail because another thread created a resource in between.
136
        @copydetails ResourceManager::createResource
137
        @return A pair, the first element being the pointer, and the second being 
138
            an indicator specifying whether the resource was newly created.
139
        */
140
        ResourceCreateOrRetrieveResult createOrRetrieve(const String& name,
141
            const String& group, bool isManual = false, 
142
            ManualResourceLoader* loader = 0, 
143
            const NameValuePairList* createParams = 0);
144
        
145
        /** Set a limit on the amount of memory this resource handler may use.
146
147
            If, when asked to load a new resource, the manager believes it will exceed this memory
148
            budget, it will temporarily unload a resource to make room for the new one. This unloading
149
            is not permanent and the Resource is not destroyed; it simply needs to be reloaded when
150
            next used.
151
        */
152
        void setMemoryBudget(size_t bytes);
153
154
        /** Get the limit on the amount of memory this resource handler may use.
155
        */
156
        size_t getMemoryBudget(void) const;
157
158
        /** Gets the current memory usage, in bytes. */
159
0
        size_t getMemoryUsage(void) const { return mMemoryUsage.load(); }
160
161
        /** Unloads a single resource by name.
162
163
            Unloaded resources are not removed, they simply free up their memory
164
            as much as they can and wait to be reloaded.
165
            @see ResourceGroupManager for unloading of resource groups.
166
        */
167
        void  unload(const String& name, const String& group OGRE_RESOURCE_GROUP_INIT);
168
        
169
        /** Unloads a single resource by handle.
170
171
            Unloaded resources are not removed, they simply free up their memory
172
            as much as they can and wait to be reloaded.
173
            @see ResourceGroupManager for unloading of resource groups.
174
        */
175
        void unload(ResourceHandle handle);
176
177
        /** Unloads all resources.
178
179
            Unloaded resources are not removed, they simply free up their memory
180
            as much as they can and wait to be reloaded.
181
            @see ResourceGroupManager for unloading of resource groups.
182
        @param reloadableOnly If true (the default), only unload the resource that
183
            is reloadable. Because some resources isn't reloadable, they will be
184
            unloaded but can't load them later. Thus, you might not want to them
185
            unloaded. Or, you might unload all of them, and then populate them
186
            manually later.
187
            @see Resource::isReloadable for resource is reloadable.
188
        */
189
        void unloadAll(bool reloadableOnly = true)
190
0
            { unloadAll(reloadableOnly ? Resource::LF_DEFAULT : Resource::LF_INCLUDE_NON_RELOADABLE); }
191
192
        /** Caused all currently loaded resources to be reloaded.
193
194
            All resources currently being held in this manager which are also
195
            marked as currently loaded will be unloaded, then loaded again.
196
        @param reloadableOnly If true (the default), only reload the resource that
197
            is reloadable. Because some resources isn't reloadable, they will be
198
            unloaded but can't loaded again. Thus, you might not want to them
199
            unloaded. Or, you might unload all of them, and then populate them
200
            manually later.
201
            @see Resource::isReloadable for resource is reloadable.
202
        */
203
        void reloadAll(bool reloadableOnly = true)
204
0
            { reloadAll(reloadableOnly ? Resource::LF_DEFAULT : Resource::LF_INCLUDE_NON_RELOADABLE); }
205
206
        /** Unload all resources which are not referenced by any other object.
207
208
            This method behaves like unloadAll, except that it only unloads resources
209
            which are not in use, ie not referenced by other objects. This allows you
210
            to free up some memory selectively whilst still keeping the group around
211
            (and the resources present, just not using much memory).
212
        @par
213
            Some referenced resource may exists 'weak' pointer to their sub-components
214
            (e.g. Entity held pointer to SubMesh), in this case, unload or reload that
215
            resource will cause dangerous pointer access. Use this function instead of
216
            unloadAll allows you avoid fail in those situations.
217
        @param reloadableOnly If true (the default), only unloads resources
218
            which can be subsequently automatically reloaded.
219
        */
220
        void unloadUnreferencedResources(bool reloadableOnly = true)
221
0
            { unloadAll(reloadableOnly ? Resource::LF_ONLY_UNREFERENCED : Resource::LF_ONLY_UNREFERENCED_INCLUDE_NON_RELOADABLE); }
222
223
        /** Caused all currently loaded but not referenced by any other object
224
            resources to be reloaded.
225
226
            This method behaves like reloadAll, except that it only reloads resources
227
            which are not in use, i.e. not referenced by other objects.
228
        @par
229
            Some referenced resource may exists 'weak' pointer to their sub-components
230
            (e.g. Entity held pointer to SubMesh), in this case, unload or reload that
231
            resource will cause dangerous pointer access. Use this function instead of
232
            reloadAll allows you avoid fail in those situations.
233
        @param reloadableOnly If true (the default), only reloads resources
234
            which can be subsequently automatically reloaded.
235
        */
236
        void reloadUnreferencedResources(bool reloadableOnly = true)
237
0
            { reloadAll(reloadableOnly ? Resource::LF_ONLY_UNREFERENCED : Resource::LF_ONLY_UNREFERENCED_INCLUDE_NON_RELOADABLE); }
238
239
        /** Unloads all resources.
240
241
            Unloaded resources are not removed, they simply free up their memory
242
            as much as they can and wait to be reloaded.
243
            @see ResourceGroupManager for unloading of resource groups.
244
        @param flags Allow to restrict processing to only reloadable and/or
245
            unreferenced resources.
246
            @see Resource::LoadingFlags for additional information.
247
        */
248
        virtual void unloadAll(Resource::LoadingFlags flags);
249
250
        /** Caused all currently loaded resources to be reloaded.
251
252
            All resources currently being held in this manager which are also
253
            marked as currently loaded will be unloaded, then loaded again.
254
        @param flags Allow to restrict processing to only reloadable and/or
255
            unreferenced resources. Additionally, reloading could be done with
256
            preserving some selected resource states that could be used elsewhere.
257
            @see Resource::LoadingFlags for additional information.
258
        */
259
        virtual void reloadAll(Resource::LoadingFlags flags);
260
261
        /** Remove a single resource.
262
263
            Removes a single resource, meaning it will be removed from the list
264
            of valid resources in this manager, also causing it to be unloaded. 
265
        @note
266
            The word 'Destroy' is not used here, since
267
            if any other pointers are referring to this resource, it will persist
268
            until they have finished with it; however to all intents and purposes
269
            it no longer exists and will likely get destroyed imminently.
270
        @note
271
            If you do have shared pointers to resources hanging around after the 
272
            ResourceManager is destroyed, you may get problems on destruction of
273
            these resources if they were relying on the manager (especially if
274
            it is a plugin). If you find you get problems on shutdown in the
275
            destruction of resources, try making sure you release all your
276
            shared pointers before you shutdown OGRE.
277
        */
278
        void remove(const ResourcePtr& r);
279
280
        /// @overload
281
        void remove(const String& name, const String& group OGRE_RESOURCE_GROUP_INIT);
282
        
283
        /// @overload
284
        void remove(ResourceHandle handle);
285
        /** Removes all resources.
286
        @note
287
            The word 'Destroy' is not used here, since
288
            if any other pointers are referring to these resources, they will persist
289
            until they have been finished with; however to all intents and purposes
290
            the resources no longer exist and will get destroyed imminently.
291
        @note
292
            If you do have shared pointers to resources hanging around after the 
293
            ResourceManager is destroyed, you may get problems on destruction of
294
            these resources if they were relying on the manager (especially if
295
            it is a plugin). If you find you get problems on shutdown in the
296
            destruction of resources, try making sure you release all your
297
            shared pointers before you shutdown OGRE.
298
        */
299
        virtual void removeAll(void);
300
301
        /** Remove all resources which are not referenced by any other object.
302
303
            This method behaves like removeAll, except that it only removes resources
304
            which are not in use, ie not referenced by other objects. This allows you
305
            to free up some memory selectively whilst still keeping the group around
306
            (and the resources present, just not using much memory).
307
        @par
308
            Some referenced resource may exists 'weak' pointer to their sub-components
309
            (e.g. Entity held pointer to SubMesh), in this case, remove or reload that
310
            resource will cause dangerous pointer access. Use this function instead of
311
            removeAll allows you avoid fail in those situations.
312
        @param reloadableOnly If true (the default), only removes resources
313
            which can be subsequently automatically reloaded.
314
        */
315
        virtual void removeUnreferencedResources(bool reloadableOnly = true);
316
317
        /** Retrieves a pointer to a resource by name, or null if the resource does not exist.
318
        */
319
        virtual ResourcePtr getResourceByName(const String& name, const String& groupName OGRE_RESOURCE_GROUP_INIT) const;
320
321
        /** Retrieves a pointer to a resource by handle, or null if the resource does not exist.
322
        */
323
        virtual ResourcePtr getByHandle(ResourceHandle handle) const;
324
        
325
        /// Returns whether the named resource exists in this manager
326
        bool resourceExists(const String& name, const String& group OGRE_RESOURCE_GROUP_INIT) const
327
0
        {
328
0
            return getResourceByName(name, group).get() != 0;
329
0
        }
330
        /// Returns whether a resource with the given handle exists in this manager
331
        bool resourceExists(ResourceHandle handle) const
332
0
        {
333
0
            return getByHandle(handle).get() != 0;
334
0
        }
335
336
        /** Notify this manager that a resource which it manages has been 
337
            'touched', i.e. used. 
338
        */
339
        virtual void _notifyResourceTouched(Resource* res);
340
341
        /** Notify this manager that a resource which it manages has been 
342
            loaded. 
343
        */
344
        virtual void _notifyResourceLoaded(Resource* res);
345
346
        /** Notify this manager that a resource which it manages has been 
347
            unloaded.
348
        */
349
        virtual void _notifyResourceUnloaded(Resource* res);
350
351
        /** Generic prepare method, used to create a Resource specific to this 
352
            ResourceManager without using one of the specialised 'prepare' methods
353
            (containing per-Resource-type parameters).
354
        @param name The name of the %Resource
355
        @param group The resource group to which this resource will belong
356
        @param isManual Is the resource to be manually loaded? If so, you should
357
            provide a value for the loader parameter
358
        @param loader The manual loader which is to perform the required actions
359
            when this resource is loaded; only applicable when you specify true
360
            for the previous parameter
361
        @param loadParams Optional pointer to a list of name/value pairs 
362
            containing loading parameters for this type of resource.
363
        @param backgroundThread Optional boolean which lets the load routine know if it
364
            is being run on the background resource loading thread
365
        */
366
        ResourcePtr prepare(const String& name,
367
            const String& group, bool isManual = false, 
368
            ManualResourceLoader* loader = 0, const NameValuePairList* loadParams = 0,
369
            bool backgroundThread = false);
370
371
        /** Generic load method, used to create a Resource specific to this 
372
            ResourceManager without using one of the specialised 'load' methods
373
            (containing per-Resource-type parameters).
374
        @copydetails ResourceManager::prepare()
375
        */
376
        ResourcePtr load(const String& name,
377
            const String& group, bool isManual = false, 
378
            ManualResourceLoader* loader = 0, const NameValuePairList* loadParams = 0,
379
            bool backgroundThread = false);
380
381
0
        const StringVector& getScriptPatterns(void) const override { return mScriptPatterns; }
382
        void parseScript(DataStreamPtr& stream, const String& groupName) override;
383
0
        Real getLoadingOrder(void) const override { return mLoadOrder; }
384
385
        /** Gets a string identifying the type of resource this manager handles. */
386
0
        const String& getResourceType(void) const { return mResourceType; }
387
388
        /** Sets whether this manager and its resources habitually produce log output */
389
0
        void setVerbose(bool v) { mVerbose = v; }
390
391
        /** Gets whether this manager and its resources habitually produce log output */
392
0
        bool getVerbose(void) { return mVerbose; }
393
394
        /** Definition of a pool of resources, which users can use to reuse similar
395
            resources many times without destroying and recreating them.
396
397
            This is a simple utility class which allows the reuse of resources
398
            between code which has a changing need for them. For example, 
399
        */
400
        class _OgreExport ResourcePool : public Pool<ResourcePtr>, public ResourceAlloc
401
        {
402
            String mName;
403
        public:
404
            ResourcePool(const String& name);
405
            ~ResourcePool();
406
            /// Get the name of the pool
407
            const String& getName() const;
408
            void clear() override;
409
        };
410
        
411
        /// Create a resource pool, or reuse one that already exists
412
        ResourcePool* getResourcePool(const String& name);
413
        /// Destroy a resource pool
414
        void destroyResourcePool(ResourcePool* pool);
415
        /// Destroy a resource pool
416
        void destroyResourcePool(const String& name);
417
        /// destroy all pools
418
        void destroyAllResourcePools();
419
420
421
422
423
    protected:
424
425
        /** Allocates the next handle. */
426
        ResourceHandle getNextHandle(void);
427
428
        /** Create a new resource instance compatible with this manager (no custom 
429
            parameters are populated at this point). 
430
431
            Subclasses must override this method and create a subclass of Resource.
432
        @param name The unique name of the resource
433
        @param handle The unique handle of the resource
434
        @param group The name of the resource group to attach this new resource to
435
        @param isManual Is this resource manually loaded? If so, you should really
436
            populate the loader parameter in order that the load process
437
            can call the loader back when loading is required. 
438
        @param loader Pointer to a ManualLoader implementation which will be called
439
            when the Resource wishes to load (should be supplied if you set
440
            isManual to true). You can in fact leave this parameter null 
441
            if you wish, but the Resource will never be able to reload if 
442
            anything ever causes it to unload. Therefore provision of a proper
443
            ManualLoader instance is strongly recommended.
444
        @param createParams If any parameters are required to create an instance,
445
            they should be supplied here as name / value pairs. These do not need 
446
            to be set on the instance (handled elsewhere), just used if required
447
            to differentiate which concrete class is created.
448
449
        */
450
        virtual Resource* createImpl(const String& name, ResourceHandle handle, 
451
            const String& group, bool isManual, ManualResourceLoader* loader, 
452
            const NameValuePairList* createParams) = 0;
453
        /** Add a newly created resource to the manager (note weak reference) */
454
        virtual void addImpl( ResourcePtr& res );
455
        /** Remove a resource from this manager; remove it from the lists. */
456
        virtual void removeImpl(const ResourcePtr& res );
457
        /** Checks memory usage and pages out if required. This is automatically done after a new resource is loaded.
458
        */
459
        void checkUsage(void);
460
461
462
    public:
463
        typedef std::unordered_map< String, ResourcePtr > ResourceMap;
464
        typedef std::unordered_map< String, ResourceMap > ResourceWithGroupMap;
465
        typedef std::map<ResourceHandle, ResourcePtr> ResourceHandleMap;
466
    protected:
467
        ResourceHandleMap mResourcesByHandle;
468
        ResourceMap mResources;
469
        ResourceWithGroupMap mResourcesWithGroup;
470
        size_t mMemoryBudget; /// In bytes
471
        std::atomic<ResourceHandle> mNextHandle;
472
        std::atomic<size_t> mMemoryUsage; /// In bytes
473
474
        bool mVerbose;
475
476
        // IMPORTANT - all subclasses must populate the fields below
477
478
        /// Patterns to use to look for scripts if supported (e.g. *.overlay)
479
        StringVector mScriptPatterns; 
480
        /// Loading order relative to other managers, higher is later
481
        Real mLoadOrder; 
482
        /// String identifying the resource type this manager handles
483
        String mResourceType; 
484
485
    public:
486
        typedef MapIterator<ResourceHandleMap> ResourceMapIterator;
487
        /** Returns an iterator over all resources in this manager. 
488
        @note
489
            Use of this iterator is NOT thread safe!
490
        */
491
        ResourceMapIterator getResourceIterator(void) 
492
0
        {
493
0
            return ResourceMapIterator(mResourcesByHandle.begin(), mResourcesByHandle.end());
494
0
        }
495
496
    protected:
497
        typedef std::map<String, ResourcePool*> ResourcePoolMap;
498
        ResourcePoolMap mResourcePoolMap;
499
    };
500
501
    /** @} */
502
    /** @} */
503
504
}
505
506
#include "OgreHeaderSuffix.h"
507
508
#endif