Canvas: use weak pointer to protect parent element access.

Using a weak pointer is the best way to ensure no invalid
pointer is used. This also fixes a possible crash in
simgear::canvas::Element::getParentStyle on destructing
canvas elements.
This commit is contained in:
Thomas Geymayer 2015-09-29 21:38:52 +02:00
parent 3bfd0c872a
commit 00a20409f7
12 changed files with 25 additions and 36 deletions

View File

@ -207,19 +207,6 @@ namespace canvas
//----------------------------------------------------------------------------
Element::~Element()
{
if( !_transform.valid() )
return;
for(unsigned int i = 0; i < _transform->getNumChildren(); ++i)
{
OSGUserData* ud =
static_cast<OSGUserData*>(_transform->getChild(i)->getUserData());
if( ud )
// Ensure parent is cleared to prevent accessing released memory if an
// element somehow survives longer than his parent.
ud->element->_parent = 0;
}
}
//----------------------------------------------------------------------------
@ -246,7 +233,7 @@ namespace canvas
//----------------------------------------------------------------------------
ElementPtr Element::getParent() const
{
return _parent;
return _parent.lock();
}
//----------------------------------------------------------------------------
@ -324,8 +311,9 @@ namespace canvas
//----------------------------------------------------------------------------
bool Element::ascend(EventVisitor& visitor)
{
if( _parent )
return _parent->accept(visitor);
ElementPtr parent = getParent();
if( parent )
return parent->accept(visitor);
return true;
}
@ -374,9 +362,9 @@ namespace canvas
EventPropagationPath path;
path.push_back( EventTarget(this) );
for( Element* parent = _parent;
parent != NULL;
parent = parent->_parent )
for( ElementPtr parent = getParent();
parent.valid();
parent = parent->getParent() )
path.push_front( EventTarget(parent) );
CanvasPtr canvas = _canvas.lock();
@ -772,7 +760,7 @@ namespace canvas
Element::Element( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent ):
ElementWeakPtr parent ):
PropertyBasedElement(node),
_canvas( canvas ),
_parent( parent ),
@ -871,11 +859,12 @@ namespace canvas
Element::getParentStyle(const SGPropertyNode* child) const
{
// Try to get value from parent...
if( _parent )
ElementPtr parent = getParent();
if( parent )
{
Style::const_iterator style =
_parent->_style.find(child->getNameString());
if( style != _parent->_style.end() )
parent->_style.find(child->getNameString());
if( style != parent->_style.end() )
return style->second;
}

View File

@ -232,8 +232,8 @@ namespace canvas
class RelativeScissor;
CanvasWeakPtr _canvas;
Element *_parent;
CanvasWeakPtr _canvas;
ElementWeakPtr _parent;
mutable uint32_t _attributes_dirty;
@ -256,7 +256,7 @@ namespace canvas
Element( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent );
ElementWeakPtr parent );
/**
* Returns false on first call and true on any successive call. Use to

View File

@ -70,7 +70,7 @@ namespace canvas
Group::Group( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent ):
ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent)
{
staticInit();

View File

@ -45,7 +45,7 @@ namespace canvas
Group( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style = Style(),
Element* parent = 0 );
ElementWeakPtr parent = 0 );
virtual ~Group();
ElementPtr createChild( const std::string& type,

View File

@ -112,7 +112,7 @@ namespace canvas
Image::Image( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent ):
ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent),
_texture(new osg::Texture2D),
_node_src_rect( node->getNode("source", 0, true) ),

View File

@ -50,7 +50,7 @@ namespace canvas
Image( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style = Style(),
Element* parent = 0 );
ElementWeakPtr parent = 0 );
virtual ~Image();
virtual void update(double dt);

View File

@ -62,7 +62,7 @@ namespace canvas
Map::Map( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent ):
ElementWeakPtr parent ):
Group(canvas, node, parent_style, parent),
// TODO make projection configurable
_projection(new SansonFlamsteedProjection),

View File

@ -42,7 +42,7 @@ namespace canvas
Map( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent = 0 );
ElementWeakPtr parent = 0 );
virtual ~Map();
virtual void update(double dt);

View File

@ -531,7 +531,7 @@ namespace canvas
Path::Path( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent ):
ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent),
_path( new PathDrawable(this) )
{

View File

@ -36,7 +36,7 @@ namespace canvas
Path( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent = 0 );
ElementWeakPtr parent = 0 );
virtual ~Path();
virtual void update(double dt);

View File

@ -740,7 +740,7 @@ namespace canvas
Text::Text( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent ):
ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent),
_text( new Text::TextOSG(this) )
{

View File

@ -40,7 +40,7 @@ namespace canvas
Text( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node,
const Style& parent_style,
Element* parent = 0 );
ElementWeakPtr parent = 0 );
~Text();
void setText(const char* text);