Partial fix for crash in SGPropertyNode::fireValueChanged
The effect system used Listeners on property nodes to get the values for shader uniforms. These listeners get deleted by an osg thread causing access to freed memory when this happens while the main thread calls fireValueChanged. This patch changes the update method to polling for scalar properties. This isn't 100% threadsafe, too. But at least it does not crash anymore.
This commit is contained in:
parent
c30ce67e16
commit
f33ad357e9
@ -1356,6 +1356,28 @@ void Effect::InitializeCallback::doUpdate(osg::Node* node, osg::NodeVisitor* nv)
|
||||
}
|
||||
}
|
||||
|
||||
void Effect::UpdateCallback::operator()(osg::Node* node, osg::NodeVisitor* nv)
|
||||
{
|
||||
EffectGeode* eg = dynamic_cast<EffectGeode*>(node);
|
||||
if (!eg)
|
||||
return;
|
||||
Effect* effect = eg->getEffect();
|
||||
if (!effect)
|
||||
return;
|
||||
|
||||
for (vector<SGSharedPtr<Updater> >::iterator itr = effect->_extraData.begin(),
|
||||
end = effect->_extraData.end();
|
||||
itr != end;
|
||||
++itr) {
|
||||
PropertyPoller * poller
|
||||
= dynamic_cast<PropertyPoller*>(itr->ptr());
|
||||
if (poller)
|
||||
poller->pollProperties(effect);
|
||||
}
|
||||
|
||||
traverse(node, nv);
|
||||
}
|
||||
|
||||
bool Effect::Key::EqualTo::operator()(const Effect::Key& lhs,
|
||||
const Effect::Key& rhs) const
|
||||
{
|
||||
|
@ -73,6 +73,17 @@ private:
|
||||
bool _initialized;
|
||||
};
|
||||
|
||||
class PropertyPoller
|
||||
{
|
||||
public:
|
||||
PropertyPoller() {};
|
||||
virtual ~PropertyPoller() {};
|
||||
virtual void pollProperties(Effect* effect)
|
||||
{
|
||||
}
|
||||
private:
|
||||
};
|
||||
|
||||
class Effect : public osg::Object
|
||||
{
|
||||
public:
|
||||
@ -121,6 +132,17 @@ public:
|
||||
{
|
||||
void doUpdate(osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
friend struct UpdateCallback;
|
||||
struct UpdateCallback : public osg::NodeCallback
|
||||
{
|
||||
UpdateCallback() {}
|
||||
UpdateCallback(const UpdateCallback& nc, const osg::CopyOp& copyop)
|
||||
: osg::NodeCallback(nc, copyop)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
|
||||
};
|
||||
protected:
|
||||
std::vector<SGSharedPtr<Updater> > _extraData;
|
||||
~Effect();
|
||||
|
@ -496,19 +496,17 @@ make_OSGFunctor(Obj* obj, void (Obj::*const func)(const OSGParam&))
|
||||
template<typename OSGParamType, typename ObjType, typename F>
|
||||
class ScalarChangeListener
|
||||
: public SGPropertyChangeListener, public InitializeWhenAdded,
|
||||
public PropertyPoller,
|
||||
public Effect::Updater
|
||||
{
|
||||
public:
|
||||
ScalarChangeListener(ObjType* obj, const F& setter,
|
||||
const std::string& propName)
|
||||
: _obj(obj), _setter(setter)
|
||||
: _obj(obj), _setter(setter), _propName(propName)
|
||||
{
|
||||
_propName = new std::string(propName);
|
||||
}
|
||||
virtual ~ScalarChangeListener()
|
||||
{
|
||||
delete _propName;
|
||||
_propName = 0;
|
||||
}
|
||||
void valueChanged(SGPropertyNode* node)
|
||||
{
|
||||
@ -516,16 +514,20 @@ public:
|
||||
}
|
||||
void initOnAddImpl(Effect* effect, SGPropertyNode* propRoot)
|
||||
{
|
||||
SGPropertyNode* listenProp = makeNode(propRoot, *_propName);
|
||||
delete _propName;
|
||||
_propName = 0;
|
||||
if (listenProp)
|
||||
listenProp->addChangeListener(this, true);
|
||||
_listenProp = makeNode(propRoot, _propName);
|
||||
// if ( _listenProp.valid() )
|
||||
// _listenProp->addChangeListener(this, true);
|
||||
}
|
||||
void pollProperties(Effect* effect)
|
||||
{
|
||||
if( false == _listenProp.valid() ) return;
|
||||
valueChanged(_listenProp);
|
||||
}
|
||||
private:
|
||||
SGPropertyNode_ptr _listenProp;
|
||||
osg::ref_ptr<ObjType> _obj;
|
||||
F _setter;
|
||||
std::string* _propName;
|
||||
std::string _propName;
|
||||
};
|
||||
|
||||
template<typename T, typename Func>
|
||||
|
@ -52,7 +52,9 @@ void EffectGeode::setEffect(Effect* effect)
|
||||
_effect = effect;
|
||||
if (!_effect)
|
||||
return;
|
||||
//TODO: do we leak the callbacks or does the geode own pointer afterwards?
|
||||
addUpdateCallback(new Effect::InitializeCallback);
|
||||
addUpdateCallback(new Effect::UpdateCallback);
|
||||
}
|
||||
|
||||
void EffectGeode::resizeGLObjectBuffers(unsigned int maxSize)
|
||||
|
Loading…
Reference in New Issue
Block a user