Added a DeleteHandler into osg::Referenced so that it can delete objects

via a seperate delete handler.  Useful for making unref()/ref() thread safe if
the users needs to address this issue.
This commit is contained in:
Robert Osfield 2002-12-16 10:25:31 +00:00
parent cb87e7b3bc
commit 884b2730e8
5 changed files with 96 additions and 22 deletions

View File

@ -333,6 +333,10 @@ SOURCE=..\..\src\osg\Projection.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File
SOURCE=..\..\src\osg\Referenced.cpp
# End Source File
# Begin Source File
SOURCE=..\..\src\osg\ShapeDrawable.cpp SOURCE=..\..\src\osg\ShapeDrawable.cpp
# End Source File # End Source File
# Begin Source File # Begin Source File

View File

@ -16,7 +16,7 @@ namespace osg {
* the standard pure virtual clone, isSameKindAs and className methods * the standard pure virtual clone, isSameKindAs and className methods
* which are required for all Object subclasses.*/ * which are required for all Object subclasses.*/
#define META_Object(library,name) \ #define META_Object(library,name) \
virtual osg::Object* cloneType() const { return osgNew name (); } \ virtual osg::Object* cloneType() const { return new name (); } \
virtual osg::Object* clone(const osg::CopyOp& copyop) const { return osgNew name (*this,copyop); } \ virtual osg::Object* clone(const osg::CopyOp& copyop) const { return osgNew name (*this,copyop); } \
virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const name *>(obj)!=NULL; } \ virtual bool isSameKindAs(const osg::Object* obj) const { return dynamic_cast<const name *>(obj)!=NULL; } \
virtual const char* libraryName() const { return #library; }\ virtual const char* libraryName() const { return #library; }\

View File

@ -9,6 +9,11 @@
namespace osg { namespace osg {
// forward declar, declared after Refenced below.
class DeleteHandler;
/** Base class from providing referencing counted objects.*/ /** Base class from providing referencing counted objects.*/
class SG_EXPORT Referenced class SG_EXPORT Referenced
{ {
@ -31,6 +36,13 @@ class SG_EXPORT Referenced
inline Referenced& operator = (Referenced&) { return *this; } inline Referenced& operator = (Referenced&) { return *this; }
friend DeleteHandler;
static void setDeleteHandler(DeleteHandler* handler);
static DeleteHandler* getDeleteHandler();
/** increment the reference count by one, indicating that /** increment the reference count by one, indicating that
this object has another pointer which is referencing it.*/ this object has another pointer which is referencing it.*/
inline void ref() const { ++_refCount; } inline void ref() const { ++_refCount; }
@ -39,7 +51,7 @@ class SG_EXPORT Referenced
a pointer to this object is referencing it. If the a pointer to this object is referencing it. If the
reference count goes to zero, it is assumed that this object reference count goes to zero, it is assumed that this object
is no longer referenced and is automatically deleted.*/ is no longer referenced and is automatically deleted.*/
inline void unref() const { --_refCount; if (_refCount<=0) delete this; } inline void unref() const;
/** decrement the reference count by one, indicating that /** decrement the reference count by one, indicating that
a pointer to this object is referencing it. However, do a pointer to this object is referencing it. However, do
@ -60,9 +72,13 @@ class SG_EXPORT Referenced
inline static int deletedCount() { return _deletedCount; } inline static int deletedCount() { return _deletedCount; }
#endif #endif
protected: protected:
virtual ~Referenced(); virtual ~Referenced();
mutable int _refCount; mutable int _refCount;
#ifdef OSG_COMPILE_UNIT_TESTS #ifdef OSG_COMPILE_UNIT_TESTS
static int _createdCount; // incremented in the constructor static int _createdCount; // incremented in the constructor
static int _deletedCount; // incremented in the destructor static int _deletedCount; // incremented in the destructor
@ -70,6 +86,38 @@ class SG_EXPORT Referenced
}; };
/** Class for override the default delete behavior so that users can implment their own object
* deletion schemes. This might be done to help implement protection of multiple threads from deleting
* objects unintentionally.*/
class DeleteHandler
{
public:
virtual ~DeleteHandler() {}
/** flush any cache of objects that need to be deleted by doing an actual delete.*/
virtual void flush() {}
inline void doDelete(const Referenced* object) { delete object; }
/** Request the deletion of an object.
* Depending on users implementation of DeleteHandler, the delete of the object may occur
* straight away or be delayed until doDelete is called.
* The default implementation does a delete straight away.*/
virtual void requestDelete(const Referenced* object) { doDelete(object); }
};
inline void Referenced::unref() const
{
--_refCount;
if (_refCount<=0)
{
if (getDeleteHandler()) getDeleteHandler()->requestDelete(this);
else delete this;
}
}
} }
#endif #endif

View File

@ -1,28 +1,12 @@
#include <osg/Object> #include <osg/Object>
#include <osg/Notify>
#include <typeinfo>
using namespace osg; namespace osg
#ifdef OSG_COMPILE_UNIT_TESTS
int Referenced::_createdCount = 0;
int Referenced::_deletedCount = 0;
#endif
Referenced::~Referenced()
{ {
if (_refCount>0)
{
notify(WARN)<<"Warning: deleting still referenced object "<<this<<" of type '"<<typeid(this).name()<<"'"<<std::endl;
notify(WARN)<<" the final reference count was "<<_refCount<<", memory corruption possible."<<std::endl;
}
#ifdef OSG_COMPILE_UNIT_TESTS
_deletedCount ++;
#endif
}
Object::Object(const Object& obj,const CopyOp& copyop): Object::Object(const Object& obj,const CopyOp& copyop):
Referenced(), Referenced(),
_dataVariance(obj._dataVariance), _dataVariance(obj._dataVariance),
_userData(copyop(obj._userData.get())) {} _userData(copyop(obj._userData.get())) {}
}; // end of namespace osg

38
src/osg/Referenced.cpp Normal file
View File

@ -0,0 +1,38 @@
#include <osg/Referenced>
#include <osg/Notify>
#include <typeinfo>
namespace osg
{
static std::auto_ptr<DeleteHandler> s_deleteHandler(0);
void Referenced::setDeleteHandler(DeleteHandler* handler)
{
s_deleteHandler.reset(handler);
}
DeleteHandler* Referenced::getDeleteHandler()
{
return s_deleteHandler.get();
}
#ifdef OSG_COMPILE_UNIT_TESTS
int Referenced::_createdCount = 0;
int Referenced::_deletedCount = 0;
#endif
Referenced::~Referenced()
{
if (_refCount>0)
{
notify(WARN)<<"Warning: deleting still referenced object "<<this<<" of type '"<<typeid(this).name()<<"'"<<std::endl;
notify(WARN)<<" the final reference count was "<<_refCount<<", memory corruption possible."<<std::endl;
}
#ifdef OSG_COMPILE_UNIT_TESTS
_deletedCount ++;
#endif
}
}; // end of namespace osg