|
OpenTop 1.3 | |||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | Cross-Platform C++ | ||||
SUMMARY: CONSTRUCTOR | METHOD | DETAIL: CONSTRUCTOR | METHOD |
#include "ot/base/ManagedObject.h"
Common base class for all classes that rely on reference-counting to perform automatic object lifetime management.
Object lifetime management (aka 'garbage collection') is the process of deciding when an object is no longer needed and destroying it when it is safe to do so.Unlike many other languages, C++ does not offer any native object lifetime management facilities - the programmer is generally responsible for keeping track of when objects are created and destroyed.
While the manual approach to memory management is good and efficient for some systems, it can place an unnecessary burden on the programmer and some useful programming practices can become virtually impossible. A case in point is the idea of 'filters'. A filter class implements the same interface as another class, overriding some methods and delegating all other calls to a contained object (see FilterInputStream for an example). When using a manual approach, the user of a filter would have to decide who was responsible for the ownership of the contained object - the creator or the filter. Should the filter delete the object when it is itself destroyed? What if something else is relying on that object elsewhere in the program? These types of questions make systems development complicated. OpenTop employs a reference-counting scheme that allows the ownership of an object to be shared by all users of it - and the object is responsible for destroying itself when it is no longer referenced.
Much of the OpenTop library is inspired by the Java API (JDK). The Java API is considerably easier to use and richer than the equivalent C++ standard library. The designers of OpenTop believe that the JDK achieves much of its power and flexibility by being able to create objects on the fly in the knowledge that they will be destroyed when they are no longer used.
Using reference-counting in this way makes the behaviour of a class deterministic. Resources are always freed at the point when the object is no longer referenced.
Just like in COM, this scheme puts a requirement on each client program to release references to objects that it has received. However, as OpenTop is written in C++, this burden is delegated to a template class called RefPtr<T> which takes care of most of the boiler plate code required to correctly perform object reference-counting.
There are various techniques that can be employed to prevent cyclic references. One effective technique is to establish the part of a class which is causing the dependency and factor that out into another class that both objects can reference. In this way we go from A<-->B which is cyclic to A-->C<--B which isn't.
Another possible technique involves the use of native pointers or references to classes that always have a lifetime that envelopes the referring object.
Whichever technique is chosen, it is important to monitor applications built using reference-counting to ensure that resource exhaustion does not occur due to cyclic references. It is a good idea to use a memory leak detector during development to help isolate these problems. When using Visual C++ on the Microsoft Windows platform, the MemCheckSystemMonitor class can be used to invoke the built-in memory-leak detection of the C run-time library.
This scheme also allows derived class constructors to throw exceptions without leaving an invalid reference-count in the base object.
Please note, however, that great care should be taken when creating a ManagedObject on the stack. In particular the object should not be passed to another function that may increment the reference-count. This is because, when the reference-count is decremented, the object will attempt to destroy itself - which is not legal for stack-based objects. Unless you are absolutely sure about how the object will be used it is often preferable to avoid stack-based ManagedObjects altogether.
When deciding whether or not a class should derive from ManagedObject, the following guidelines are useful:-
Factors indicating a preference towards ManagedObject:-
This does not mean, however, that classes derived from ManagedObject are automatically thread-safe. In order to be safely used by multiple threads, derived classes will have to ensure that they protect their internal state from the potential memory corruption that can result from conflicting concurrent access.
In general, with the exception of the reference-count, classes within the OpenTop library do not protect their internal state from concurrent multi-threaded access.
Constructor/Destructor Summary | |
ManagedObject() Default constructor. | |
ManagedObject(const ManagedObject& rhs) Copy constructor. | |
~ManagedObject() Destructor. |
Method Summary | |
void |
addRef() Increments the reference-count of the object. |
unsigned long |
getRefCount() const Returns the current reference-count of the object. |
virtual void |
onFinalRelease() Virtual method called when the object's reference-count has been decremented to zero. |
ManagedObject& |
operator=(const ManagedObject& rhs) Assignment operator. |
void |
release() Decrements the reference-count of the object. |
Constructor/Destructor Detail |
ManagedObject()
ManagedObject(const ManagedObject& rhs)
rhs
- virtual ~ManagedObject()
Method Detail |
void addRef()
In the debug build, an assertion is made that the reference-count is not equal to zero after it has been incremented. This check can help to trap errors where an object has been erroneously deleted.
unsigned long getRefCount() const
virtual void onFinalRelease()
Only override this method if you need to perform some other custom garbage collection.
ManagedObject& operator=(const ManagedObject& rhs)
rhs
- void release()
In multi-threaded versions of the library, the reference-count is decremented using an atomic, thread-safe operation.
|
OpenTop 1.3 | |||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | Cross-Platform C++ | ||||
SUMMARY: CONSTRUCTOR | METHOD | DETAIL: CONSTRUCTOR | METHOD |