Resource Management System -- Part 1
This is the first in a series of posts to build a reference counted "resource" management system for your game/graphics engine. First of all, what defines a resource? For our purposes, there are several conditions that determine what can be used as a resource:
- It can be used by multiple clients, and needs to be reference counted.
- Most of the clients of these objects do not need raw pointers most of the time.
- There should be a master list of all of these objects somewhere.
- Even when this object is not used, we may want to defer destruction of it for any reason.
Here's a quick rundown of the system we're going to build. Each type of resource will be managed completely seperately; we make no attempt to fuse all the resources together via base classes and using RTTI to cast them. It's just not worth the effort. We will have handles to resources, which are the main currency handed around when working with resources. Finally there will be the manager, who maintains the list of resources, deals with resource creation and destruction, and allows access to raw pointers if desired. To start with, we'll write up a base class that allows an object to be reference counted.
class RefCountedBase { private: unsigned int m_RefCount; public: RefCountedBase() : m_RefCount( 0 ) { } unsigned int RefCount() const { return m_RefCount; } unsigned int AddRef() { return ++m_RefCount; } unsigned int Release() { assert( m_RefCount > 0 ); return --m_RefCount; } };
- Any user constructed handle (that is, a new handle not generated from inside a manager) is always invalid.
- Invalid handles don't affect any reference counts, since they have no object to affect.
- The handle should decrement the reference count of its resource when destroyed.
- The copy constructor should increment the reference count of the resource.
- Assignment should decrement the current reference count, assign, and increment the reference count of the new resource.
- A handle does not include a direct pointer to its resource. This helps discourage access to the resource, unless you really need it.
- Handles can be compared with == and !=.
- Handles can be used for any reference counted type.
A resource manager has one really important responsibility -- it's the only one which has actual pointers to the resources in question. There is no other way to get access to these pointers. If you're not part of the subsystem which contains the manager, you can never access those pointers. As a result, all managers have three main responsibilities:
- Maintain the list of resources.
- Provide a way to flush unused resources out of memory.
- Receive the requests from handles to alter reference counts.
That really just about covers it for design. For part 2, we'll cover the implementation of handles and managers, and tie everything together
1 Comments:
Patiently awaiting part III! (well, maybe not so patiently.)
By
Anonymous, at 8/25/2005 2:50 PM
Post a Comment
<< Home