Added new observer_ptr templated smart pointer to allow one to retain pointers
to objects but have the pointer reset to null if that object is deleted.
This commit is contained in:
@@ -13,9 +13,11 @@
|
||||
#include <osg/Referenced>
|
||||
#include <osg/Notify>
|
||||
#include <osg/ApplicationUsage>
|
||||
#include <osg/observer_ptr>
|
||||
|
||||
#include <typeinfo>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
|
||||
#include <OpenThreads/ScopedLock>
|
||||
#include <OpenThreads/Mutex>
|
||||
@@ -25,6 +27,8 @@
|
||||
namespace osg
|
||||
{
|
||||
|
||||
typedef std::set<Observer*> ObserverSet;
|
||||
|
||||
static bool s_useThreadSafeReferenceCounting = getenv("OSG_THREAD_SAFE_REF_UNREF")!=0;
|
||||
static std::auto_ptr<DeleteHandler> s_deleteHandler(0);
|
||||
static ApplicationUsageProxy Referenced_e0(ApplicationUsage::ENVIRONMENTAL_VARIABLE,"OSG_THREAD_SAFE_REF_UNREF","");
|
||||
@@ -50,18 +54,20 @@ DeleteHandler* Referenced::getDeleteHandler()
|
||||
return s_deleteHandler.get();
|
||||
}
|
||||
|
||||
Referenced::Referenced()
|
||||
Referenced::Referenced():
|
||||
_refMutex(0),
|
||||
_refCount(0),
|
||||
_observers(0)
|
||||
{
|
||||
if (s_useThreadSafeReferenceCounting) _refMutex = new OpenThreads::Mutex;
|
||||
else _refMutex = 0;
|
||||
_refCount=0;
|
||||
}
|
||||
|
||||
Referenced::Referenced(const Referenced&)
|
||||
Referenced::Referenced(const Referenced&):
|
||||
_refMutex(0),
|
||||
_refCount(0),
|
||||
_observers(0)
|
||||
{
|
||||
if (s_useThreadSafeReferenceCounting) _refMutex = new OpenThreads::Mutex;
|
||||
else _refMutex = 0;
|
||||
_refCount=0;
|
||||
}
|
||||
|
||||
Referenced::~Referenced()
|
||||
@@ -72,6 +78,19 @@ Referenced::~Referenced()
|
||||
notify(WARN)<<" the final reference count was "<<_refCount<<", memory corruption possible."<<std::endl;
|
||||
}
|
||||
|
||||
if (_observers)
|
||||
{
|
||||
ObserverSet* os = static_cast<ObserverSet*>(_observers);
|
||||
for(ObserverSet::iterator itr = os->begin();
|
||||
itr != os->end();
|
||||
++itr)
|
||||
{
|
||||
(*itr)->objectDeleted(this);
|
||||
}
|
||||
delete os;
|
||||
_observers = 0;
|
||||
}
|
||||
|
||||
if (_refMutex)
|
||||
{
|
||||
OpenThreads::Mutex* tmpMutexPtr = _refMutex;
|
||||
@@ -151,7 +170,36 @@ void Referenced::unref_nodelete() const
|
||||
--_refCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Referenced::addObserver(Observer* observer_ptr)
|
||||
{
|
||||
if (_refMutex)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
||||
|
||||
if (!_observers) _observers = new ObserverSet;
|
||||
if (_observers) static_cast<ObserverSet*>(_observers)->insert(observer_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_observers) _observers = new ObserverSet;
|
||||
if (_observers) static_cast<ObserverSet*>(_observers)->insert(observer_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
void Referenced::removeObserver(Observer* observer_ptr)
|
||||
{
|
||||
if (_refMutex)
|
||||
{
|
||||
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(*_refMutex);
|
||||
|
||||
if (_observers) static_cast<ObserverSet*>(_observers)->erase(observer_ptr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_observers) static_cast<ObserverSet*>(_observers)->erase(observer_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
}; // end of namespace osg
|
||||
|
||||
|
||||
Reference in New Issue
Block a user