From 69f93770938db57f555c20252b46ed26ef196338 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Mon, 26 Jan 2009 15:16:24 +0000 Subject: [PATCH] Fixed effective leak in Program::PerContextProgram caused by previously osg::State keeping a set of std::ref_ptr without ever pruning this list. The fix was to convert the osg::State to use C pointers for the set of applied PerContexProgram objects, and use the osg::Oberver mechanism to avoid dangling pointers for being maintained in osg::State. --- include/osg/Referenced | 8 ++++---- include/osg/State | 22 ++++++++++++++++++---- src/osg/Referenced.cpp | 4 ++-- src/osg/State.cpp | 17 +++++++++++++++++ src/osgWrappers/osg/State.cpp | 6 ++++++ 5 files changed, 47 insertions(+), 10 deletions(-) diff --git a/include/osg/Referenced b/include/osg/Referenced index 6a8ca1ebd..f851f3dbf 100644 --- a/include/osg/Referenced +++ b/include/osg/Referenced @@ -89,10 +89,10 @@ class OSG_EXPORT Referenced inline int referenceCount() const { return _refCount; } /** Add a Observer that is observing this object, notify the Observer when this object gets deleted.*/ - void addObserver(Observer* observer); + void addObserver(Observer* observer) const; /** Add a Observer that is observing this object, notify the Observer when this object gets deleted.*/ - void removeObserver(Observer* observer); + void removeObserver(Observer* observer) const; public: @@ -121,7 +121,7 @@ class OSG_EXPORT Referenced #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS) struct ObserverSetData; - OpenThreads::AtomicPtr _observerSetDataPtr; + mutable OpenThreads::AtomicPtr _observerSetDataPtr; mutable OpenThreads::Atomic _refCount; #else @@ -130,7 +130,7 @@ class OSG_EXPORT Referenced mutable int _refCount; - void* _observers; + mutable void* _observers; #endif }; diff --git a/include/osg/State b/include/osg/State index 194168505..6214fb733 100644 --- a/include/osg/State +++ b/include/osg/State @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -84,7 +85,7 @@ class GraphicsContext; * which typically stall the graphics pipeline (see, for instance, * \c captureCurrentState() and \c getModelViewMatrix()). */ -class OSG_EXPORT State : public Referenced +class OSG_EXPORT State : public Referenced, public Observer { public : @@ -960,8 +961,19 @@ class OSG_EXPORT State : public Referenced bool isVertexBufferObjectSupported() const { return _isVertexBufferObjectSupportResolved?_isVertexBufferObjectSupported:computeVertexBufferObjectSupported(); } - void setLastAppliedProgramObject(const Program::PerContextProgram* program) { if (_lastAppliedProgramObject!=program) { _lastAppliedProgramObject = program; if (program) _appliedProgramObjectSet.insert(program); } } - const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; } + inline void setLastAppliedProgramObject(const Program::PerContextProgram* program) + { + if (_lastAppliedProgramObject!=program) + { + _lastAppliedProgramObject = program; + if (program && _appliedProgramObjectSet.count(program)==0) + { + _appliedProgramObjectSet.insert(program); + program->addObserver(this); + } + } + } + inline const Program::PerContextProgram* getLastAppliedProgramObject() const { return _lastAppliedProgramObject; } inline GLint getUniformLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getUniformLocation(name) : -1; } inline GLint getAttribLocation( const std::string& name ) const { return _lastAppliedProgramObject ? _lastAppliedProgramObject->getAttribLocation(name) : -1; } @@ -1064,6 +1076,8 @@ class OSG_EXPORT State : public Referenced /** Initialize extension used by osg:::State.*/ void initializeExtensionProcs(); + virtual void objectDeleted(void* object); + protected: virtual ~State(); @@ -1206,7 +1220,7 @@ class OSG_EXPORT State : public Referenced typedef std::vector > MatrixStack; - typedef std::set > AppliedProgramObjectSet; + typedef std::set AppliedProgramObjectSet; ModeMap _modeMap; AttributeMap _attributeMap; diff --git a/src/osg/Referenced.cpp b/src/osg/Referenced.cpp index b322ce92f..4babcac07 100644 --- a/src/osg/Referenced.cpp +++ b/src/osg/Referenced.cpp @@ -309,7 +309,7 @@ void Referenced::unref_nodelete() const #endif } -void Referenced::addObserver(Observer* observer) +void Referenced::addObserver(Observer* observer) const { #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS) ObserverSetData* observerSetData = static_cast(_observerSetDataPtr.get()); @@ -337,7 +337,7 @@ void Referenced::addObserver(Observer* observer) #endif } -void Referenced::removeObserver(Observer* observer) +void Referenced::removeObserver(Observer* observer) const { #if defined(_OSG_REFERENCED_USE_ATOMIC_OPERATIONS) ObserverSetData* observerSetData = static_cast(_observerSetDataPtr.get()); diff --git a/src/osg/State.cpp b/src/osg/State.cpp index 99f4434cd..43cc3c9bb 100644 --- a/src/osg/State.cpp +++ b/src/osg/State.cpp @@ -90,6 +90,23 @@ State::State(): State::~State() { + for(AppliedProgramObjectSet::iterator itr = _appliedProgramObjectSet.begin(); + itr != _appliedProgramObjectSet.end(); + ++itr) + { + (*itr)->removeObserver(this); + } +} + +void State::objectDeleted(void* object) +{ + const Program::PerContextProgram* ppcp = reinterpret_cast(object); + AppliedProgramObjectSet::iterator itr = _appliedProgramObjectSet.find(ppcp); + if (itr != _appliedProgramObjectSet.end()) + { + osg::notify(osg::NOTICE)<<"Removing _appliedProgramObjectSet entry "<