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-30 11:54:19 +02:00
parent 3bfd0c872a
commit 00a20409f7
12 changed files with 25 additions and 36 deletions
+12 -23
View File
@@ -207,19 +207,6 @@ namespace canvas
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
Element::~Element() 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 ElementPtr Element::getParent() const
{ {
return _parent; return _parent.lock();
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@@ -324,8 +311,9 @@ namespace canvas
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
bool Element::ascend(EventVisitor& visitor) bool Element::ascend(EventVisitor& visitor)
{ {
if( _parent ) ElementPtr parent = getParent();
return _parent->accept(visitor); if( parent )
return parent->accept(visitor);
return true; return true;
} }
@@ -374,9 +362,9 @@ namespace canvas
EventPropagationPath path; EventPropagationPath path;
path.push_back( EventTarget(this) ); path.push_back( EventTarget(this) );
for( Element* parent = _parent; for( ElementPtr parent = getParent();
parent != NULL; parent.valid();
parent = parent->_parent ) parent = parent->getParent() )
path.push_front( EventTarget(parent) ); path.push_front( EventTarget(parent) );
CanvasPtr canvas = _canvas.lock(); CanvasPtr canvas = _canvas.lock();
@@ -772,7 +760,7 @@ namespace canvas
Element::Element( const CanvasWeakPtr& canvas, Element::Element( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent ): ElementWeakPtr parent ):
PropertyBasedElement(node), PropertyBasedElement(node),
_canvas( canvas ), _canvas( canvas ),
_parent( parent ), _parent( parent ),
@@ -871,11 +859,12 @@ namespace canvas
Element::getParentStyle(const SGPropertyNode* child) const Element::getParentStyle(const SGPropertyNode* child) const
{ {
// Try to get value from parent... // Try to get value from parent...
if( _parent ) ElementPtr parent = getParent();
if( parent )
{ {
Style::const_iterator style = Style::const_iterator style =
_parent->_style.find(child->getNameString()); parent->_style.find(child->getNameString());
if( style != _parent->_style.end() ) if( style != parent->_style.end() )
return style->second; return style->second;
} }
+3 -3
View File
@@ -232,8 +232,8 @@ namespace canvas
class RelativeScissor; class RelativeScissor;
CanvasWeakPtr _canvas; CanvasWeakPtr _canvas;
Element *_parent; ElementWeakPtr _parent;
mutable uint32_t _attributes_dirty; mutable uint32_t _attributes_dirty;
@@ -256,7 +256,7 @@ namespace canvas
Element( const CanvasWeakPtr& canvas, Element( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent ); ElementWeakPtr parent );
/** /**
* Returns false on first call and true on any successive call. Use to * Returns false on first call and true on any successive call. Use to
+1 -1
View File
@@ -70,7 +70,7 @@ namespace canvas
Group::Group( const CanvasWeakPtr& canvas, Group::Group( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent ): ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent) Element(canvas, node, parent_style, parent)
{ {
staticInit(); staticInit();
+1 -1
View File
@@ -45,7 +45,7 @@ namespace canvas
Group( const CanvasWeakPtr& canvas, Group( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style = Style(), const Style& parent_style = Style(),
Element* parent = 0 ); ElementWeakPtr parent = 0 );
virtual ~Group(); virtual ~Group();
ElementPtr createChild( const std::string& type, ElementPtr createChild( const std::string& type,
+1 -1
View File
@@ -112,7 +112,7 @@ namespace canvas
Image::Image( const CanvasWeakPtr& canvas, Image::Image( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent ): ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent), Element(canvas, node, parent_style, parent),
_texture(new osg::Texture2D), _texture(new osg::Texture2D),
_node_src_rect( node->getNode("source", 0, true) ), _node_src_rect( node->getNode("source", 0, true) ),
+1 -1
View File
@@ -50,7 +50,7 @@ namespace canvas
Image( const CanvasWeakPtr& canvas, Image( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style = Style(), const Style& parent_style = Style(),
Element* parent = 0 ); ElementWeakPtr parent = 0 );
virtual ~Image(); virtual ~Image();
virtual void update(double dt); virtual void update(double dt);
+1 -1
View File
@@ -62,7 +62,7 @@ namespace canvas
Map::Map( const CanvasWeakPtr& canvas, Map::Map( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent ): ElementWeakPtr parent ):
Group(canvas, node, parent_style, parent), Group(canvas, node, parent_style, parent),
// TODO make projection configurable // TODO make projection configurable
_projection(new SansonFlamsteedProjection), _projection(new SansonFlamsteedProjection),
+1 -1
View File
@@ -42,7 +42,7 @@ namespace canvas
Map( const CanvasWeakPtr& canvas, Map( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent = 0 ); ElementWeakPtr parent = 0 );
virtual ~Map(); virtual ~Map();
virtual void update(double dt); virtual void update(double dt);
+1 -1
View File
@@ -531,7 +531,7 @@ namespace canvas
Path::Path( const CanvasWeakPtr& canvas, Path::Path( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent ): ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent), Element(canvas, node, parent_style, parent),
_path( new PathDrawable(this) ) _path( new PathDrawable(this) )
{ {
+1 -1
View File
@@ -36,7 +36,7 @@ namespace canvas
Path( const CanvasWeakPtr& canvas, Path( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent = 0 ); ElementWeakPtr parent = 0 );
virtual ~Path(); virtual ~Path();
virtual void update(double dt); virtual void update(double dt);
+1 -1
View File
@@ -740,7 +740,7 @@ namespace canvas
Text::Text( const CanvasWeakPtr& canvas, Text::Text( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent ): ElementWeakPtr parent ):
Element(canvas, node, parent_style, parent), Element(canvas, node, parent_style, parent),
_text( new Text::TextOSG(this) ) _text( new Text::TextOSG(this) )
{ {
+1 -1
View File
@@ -40,7 +40,7 @@ namespace canvas
Text( const CanvasWeakPtr& canvas, Text( const CanvasWeakPtr& canvas,
const SGPropertyNode_ptr& node, const SGPropertyNode_ptr& node,
const Style& parent_style, const Style& parent_style,
Element* parent = 0 ); ElementWeakPtr parent = 0 );
~Text(); ~Text();
void setText(const char* text); void setText(const char* text);