Fixed effective leak in Program::PerContextProgram caused by previously osg::State keeping a set of std::ref_ptr<Program::PerContextProgram> 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.
This commit is contained in:
@@ -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
|
||||
};
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <osg/Matrix>
|
||||
#include <osg/Uniform>
|
||||
#include <osg/BufferObject>
|
||||
#include <osg/observer_ptr>
|
||||
|
||||
#include <osg/FrameStamp>
|
||||
#include <osg/DisplaySettings>
|
||||
@@ -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<ref_ptr<const Matrix> > MatrixStack;
|
||||
|
||||
typedef std::set<osg::ref_ptr<const Program::PerContextProgram> > AppliedProgramObjectSet;
|
||||
typedef std::set<const Program::PerContextProgram* > AppliedProgramObjectSet;
|
||||
|
||||
ModeMap _modeMap;
|
||||
AttributeMap _attributeMap;
|
||||
|
||||
@@ -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<ObserverSetData*>(_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<ObserverSetData*>(_observerSetDataPtr.get());
|
||||
|
||||
@@ -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<const Program::PerContextProgram*>(object);
|
||||
AppliedProgramObjectSet::iterator itr = _appliedProgramObjectSet.find(ppcp);
|
||||
if (itr != _appliedProgramObjectSet.end())
|
||||
{
|
||||
osg::notify(osg::NOTICE)<<"Removing _appliedProgramObjectSet entry "<<ppcp<<std::endl;
|
||||
_appliedProgramObjectSet.erase(itr);
|
||||
}
|
||||
}
|
||||
|
||||
void State::reset()
|
||||
|
||||
@@ -43,6 +43,7 @@ END_REFLECTOR
|
||||
BEGIN_OBJECT_REFLECTOR(osg::State)
|
||||
I_DeclaringFile("osg/State");
|
||||
I_BaseType(osg::Referenced);
|
||||
I_BaseType(osg::Observer);
|
||||
I_Constructor0(____State,
|
||||
"",
|
||||
"");
|
||||
@@ -716,6 +717,11 @@ BEGIN_OBJECT_REFLECTOR(osg::State)
|
||||
__void__initializeExtensionProcs,
|
||||
"Initialize extension used by osg:State. ",
|
||||
"");
|
||||
I_Method1(void, objectDeleted, IN, void *, object,
|
||||
Properties::VIRTUAL,
|
||||
__void__objectDeleted__void_P1,
|
||||
"",
|
||||
"");
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user