/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 |