Bläddra i källkod

*** empty log message ***

David Rose 25 år sedan
förälder
incheckning
dd990450a7

+ 5 - 20
panda/src/graph/arcChain.I

@@ -35,6 +35,7 @@ ArcComponent(NodeRelation *arc, ArcComponent *next) :
   nassertv(arc != (NodeRelation *)NULL);
   _p._arc = arc;
   _p._arc->ref();
+  _p._arc->ref_parent();
 }
 
 ////////////////////////////////////////////////////////////////////
@@ -49,24 +50,7 @@ ArcComponent(const ArcComponent &copy) :
   if (has_arc()) {
     _p._arc = copy._p._arc;
     _p._arc->ref();
-  } else {
-    _p._node = copy._p._node;
-    _p._node->ref();
-  }
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: ArcChain::ArcComponent::Copy Assignment Operator
-//       Access: Public
-//  Description: 
-////////////////////////////////////////////////////////////////////
-INLINE void ArcChain::ArcComponent::
-operator = (const ArcComponent &copy) {
-  _next = copy._next;
-
-  if (has_arc()) {
-    _p._arc = copy._p._arc;
-    _p._arc->ref();
+    _p._arc->ref_parent();
   } else {
     _p._node = copy._p._node;
     _p._node->ref();
@@ -82,9 +66,10 @@ operator = (const ArcComponent &copy) {
 INLINE ArcChain::ArcComponent::
 ~ArcComponent() {
   if (has_arc()) {
-    _p._arc->unref();
+    _p._arc->unref_parent();
+    unref_delete(_p._arc);
   } else {
-    _p._node->unref();
+    unref_delete(_p._node);
   }
 }
 

+ 24 - 0
panda/src/graph/arcChain.cxx

@@ -7,6 +7,30 @@
 #include "node.h"
 #include "namedNode.h"
 
+////////////////////////////////////////////////////////////////////
+//     Function: ArcChain::ArcComponent::Copy Assignment Operator
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void ArcChain::ArcComponent::
+operator = (const ArcComponent &copy) {
+  _next = copy._next;
+
+  if (has_arc()) {
+    // Ref the new one before unreffing the old one, so we don't
+    // accidentally delete in the interim.
+    copy._p._arc->ref();
+    copy._p._arc->ref_parent();
+    _p._arc->unref_parent();
+    unref_delete(_p._arc);
+    _p._arc = copy._p._arc;
+  } else {
+    copy._p._node->ref();
+    unref_delete(_p._node);
+    _p._node = copy._p._node;
+  }
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: ArcChain::r_output
 //       Access: Private

+ 1 - 1
panda/src/graph/arcChain.h

@@ -66,7 +66,7 @@ protected:
     INLINE ArcComponent(Node *node);
     INLINE ArcComponent(NodeRelation *arc, ArcComponent *next);
     INLINE ArcComponent(const ArcComponent &copy);
-    INLINE void operator = (const ArcComponent &copy);
+    void operator = (const ArcComponent &copy);
     INLINE ~ArcComponent();
 
     INLINE bool has_arc() const;

+ 0 - 56
panda/src/graph/nodeRelation.I

@@ -3,62 +3,6 @@
 // 
 ////////////////////////////////////////////////////////////////////
 
-////////////////////////////////////////////////////////////////////
-//     Function: NodeRelation::Constructor
-//       Access: Public
-//  Description: Creates a new arc of the scene graph, and immediately
-//               attaches it.
-////////////////////////////////////////////////////////////////////
-INLINE NodeRelation::
-NodeRelation(Node *parent, Node *to, int sort, TypeHandle graph_type) :
-  _parent(parent), _child(to), _sort(sort), 
-  _graph_type(graph_type), _num_transitions(0)
-{
-  _top_subtree = NULL;
-  _attached = false;
-  attach();
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodeRelation::Constructor
-//       Access: Protected
-//  Description: Creates a new, unattached arc.  This constructor is
-//               only intended for passing through the factory to
-//               create an arc based on a particular type using
-//               create_typed_arc(), below.  You shouldn't, in
-//               general, attempt to create an unattached arc.
-////////////////////////////////////////////////////////////////////
-INLINE NodeRelation::
-NodeRelation(TypeHandle graph_type) :
-  _graph_type(graph_type)
-{
-  _parent = NULL;
-  _child = NULL;
-  _sort = 0;
-  _top_subtree = NULL;
-  _attached = false;
-  _num_transitions = 0;
-}
-
-////////////////////////////////////////////////////////////////////
-//     Function: NodeRelation::Constructor
-//       Access: Protected
-//  Description: Creates a new, unattached arc.  This constructor is
-//               only intended for being called in make_NodeRelation. 
-//               You shouldn't, in general, attempt to create an 
-//               unattached arc.
-////////////////////////////////////////////////////////////////////
-INLINE NodeRelation::
-NodeRelation(void) {
-  _parent = NULL;
-  _child = NULL;
-  _sort = 0;
-  _top_subtree = NULL;
-  _attached = false;
-  _graph_type = get_class_type();
-  _num_transitions = 0;
-}
-
 ////////////////////////////////////////////////////////////////////
 //     Function: remove_arc
 //  Description: Removes the arc from the graph, which incidentally

+ 111 - 2
panda/src/graph/nodeRelation.cxx

@@ -262,6 +262,45 @@ internal_remove_arc(ArcList &alist, NodeRelation *arc) {
 
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodeRelation::Constructor
+//       Access: Public
+//  Description: Creates a new arc of the scene graph, and immediately
+//               attaches it.
+////////////////////////////////////////////////////////////////////
+NodeRelation::
+NodeRelation(Node *parent, Node *to, int sort, TypeHandle graph_type) :
+  _parent(parent), _child(to), _sort(sort), 
+  _graph_type(graph_type), _num_transitions(0)
+{
+  _top_subtree = NULL;
+  _attached = false;
+  _parent_ref = 0;
+  attach();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodeRelation::Constructor
+//       Access: Protected
+//  Description: Creates a new, unattached arc.  This constructor is
+//               only intended for passing through the factory to
+//               create an arc based on a particular type using
+//               create_typed_arc(), below.  You shouldn't, in
+//               general, attempt to create an unattached arc.
+////////////////////////////////////////////////////////////////////
+NodeRelation::
+NodeRelation(TypeHandle graph_type) :
+  _graph_type(graph_type)
+{
+  _parent = NULL;
+  _child = NULL;
+  _sort = 0;
+  _top_subtree = NULL;
+  _attached = false;
+  _parent_ref = 0;
+  _num_transitions = 0;
+}
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeRelation::Copy Constructor
 //       Access: Private
@@ -296,6 +335,11 @@ NodeRelation::
   // delete an arc.  You should use remove_arc() instead.
   nassertv(!_attached);
 
+  // Similarly, we shouldn't be deleting arcs with a nonzero
+  // parent_ref.  This means someone lost a reference count somewhere,
+  // or someone was sloppy calling ref_parent()/unref_parent().
+  nassertv(_parent_ref == 0);
+
   _transitions.remove_all_from_arc(this);
 }
 
@@ -326,6 +370,65 @@ output(ostream &out) const {
   }
 }
 
+////////////////////////////////////////////////////////////////////
+//     Function: NodeRelation::ref_parent
+//       Access: Public
+//  Description: Normally, the arc keeps a reference count to its
+//               child node, but not to its parent node.  This allows
+//               the arc (and all of its children) to be destructed
+//               when its parent node destructs.
+//
+//               Sometimes this behavior is not desirable, and you'd
+//               like to have an arc keep a reference count to its
+//               parent.  This is particularly true when you have a
+//               reference-counting pointer to the arc in some other
+//               context, and you'd like to ensure that its parent and
+//               child node pointers are always valid while you keep
+//               the pointer.
+//
+//               In this case, you should call ref_parent() to
+//               increment the reference count on the parent node.  Be
+//               sure to call unref_parent() explicitly when you lose
+//               your reference to the arc, or you will leak reference
+//               counts.
+//
+//               Note that if the parent of the arc changes while
+//               ref_parent() is held, the old parent will
+//               automatically be dereferenced and the new parent will
+//               be referenced instead, as if it were a normal
+//               reference-counting pointer.
+////////////////////////////////////////////////////////////////////
+void NodeRelation::
+ref_parent() {
+  nassertv(_parent_ref >= 0);
+  if (_parent_ref == 0 && _attached) {
+    // If we are the first to request a reference count on the parent,
+    // actually increment it now.
+    _parent->ref();
+  }
+  _parent_ref++;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: NodeRelation::unref_parent
+//       Access: Public
+//  Description: Removes the reference count on the arc's parent node
+//               and allows the arc to be deleted normally.  See
+//               ref_parent().
+////////////////////////////////////////////////////////////////////
+void NodeRelation::
+unref_parent() {
+  nassertv(_parent_ref > 0);
+
+  _parent_ref--;
+  if (_parent_ref == 0 && _attached) {
+    // If we are the last to request a reference count on the parent,
+    // actually decrement it now.
+    _parent->unref();
+  }
+}
+
+
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeRelation::copy_transitions_from
 //       Access: Public
@@ -507,6 +610,9 @@ attach() {
   nassertv(!_attached);
 
   _attached = true;
+  if (_parent_ref != 0) {
+    _parent->ref();
+  }
 
   DownRelationPointers &parent_list = _parent->_children[_graph_type];
   UpRelationPointers &child_list = _child->_parents[_graph_type];
@@ -568,6 +674,9 @@ detach() {
   nassertr(removed_two, result);
 
   _attached = false;
+  if (_parent_ref != 0) {
+    _parent->unref();
+  }
 
   // Blow out the cache and increment the current update sequence.
   _net_transitions.clear();
@@ -813,13 +922,13 @@ complete_pointers(vector_typedWriteable &plist, BamReader *manager)
 
 ////////////////////////////////////////////////////////////////////
 //     Function: NodeRelation::make_NodeRelation
-//       Access: Protected
+//       Access: Protected, Static
 //  Description: Factory method to generate a NodeRelation object
 ////////////////////////////////////////////////////////////////////
 TypedWriteable* NodeRelation::
 make_NodeRelation(const FactoryParams &params)
 {
-  NodeRelation *me = new NodeRelation;
+  NodeRelation *me = new NodeRelation(get_class_type());
   BamReader *manager;
   Datagram packet;
 

+ 6 - 6
panda/src/graph/nodeRelation.h

@@ -47,17 +47,13 @@ extern EXPCL_PANDA UpdateSeq &last_graph_update(TypeHandle graph_type);
 ////////////////////////////////////////////////////////////////////
 class EXPCL_PANDA NodeRelation : public TypedWriteableReferenceCount, public BoundedObject {
 public:
-  INLINE NodeRelation(Node *from, Node *to, int sort, TypeHandle graph_type);
+  NodeRelation(Node *from, Node *to, int sort, TypeHandle graph_type);
 
 protected:
   // Normally, this should only be used from derived classes for
   // passing to the factory.  Don't attempt to create an unattached
   // arc directly.
-  INLINE NodeRelation(TypeHandle graph_type);
-
-  //make_NodeRelation needs to have a construct that takes nothing
-  //since it creates the object before it has any information
-  INLINE NodeRelation(void);
+  NodeRelation(TypeHandle graph_type);
 
 private:
   // It is an error to attempt to copy an arc.
@@ -82,6 +78,9 @@ PUBLISHED:
   INLINE int get_sort() const;
   INLINE TypeHandle get_graph_type() const;
 
+  void ref_parent();
+  void unref_parent();
+
   INLINE void change_parent(Node *parent);
   INLINE void change_parent(Node *parent, int sort);
   INLINE void change_child(Node *child);
@@ -145,6 +144,7 @@ private:
   int _sort;
   TypeHandle _graph_type;
   bool _attached;
+  int _parent_ref;
 
 private:
   // This is the set of transitions assigned to the arc.  You should

+ 1 - 0
panda/src/graph/wrt.I

@@ -53,6 +53,7 @@ describe_ambiguous_wrt(const Node *node,
 	    << "\n    " << *(*ri)->get_parent() << "/"
 	    << *(*ri)->get_child();
 	}
+	ri_last = ri;
 	++ri;
       } 
       wrt_cat.warning(false) << "\n";

+ 27 - 8
panda/src/sgmanip/nodePath.cxx

@@ -893,6 +893,21 @@ remove_node() {
   nassertv(has_arcs());
 
   PT(NodeRelation) darc = arc();
+
+  // Set the chain to stop here, so that any NodePaths sharing this
+  // one will now begin at this "deleted" node.
+  (*_head) = ArcComponent(_head->get_node());
+
+  // Now remove our own chain reference.  If there were no other
+  // sharing NodePaths, this will also delete the complete chain,
+  // including the above newly-changed _head node, and all of the
+  // nodes at this point and below.
+
+  // If there *are* some sharing NodePaths, they will keep this node
+  // from being actually destructed (although it has been removed from
+  // the scene graph), and they will now believe they are rooted at
+  // that destructed node, cut off from the rest of the world.
+
   clear();
   remove_arc(darc);
 }
@@ -2414,14 +2429,19 @@ r_as_string(const ArcComponent *comp, string &result, int skip_nodes) const {
 	// previous node and this node.
 
 	NodeRelation *darc = comp->get_arc();
-	if (!(darc->get_child() == (Node *)NULL ||
-	      darc->get_parent() == comp->get_next()->get_node())) {
-	  // Unless the path is broken here.  In this case, insert a
-	  // visual indication of the break.
-	  result += "/.../" + format_node_name(darc->get_parent());
+	if (darc->get_child() == (Node *)NULL &&
+	    darc->get_parent() == (Node *)NULL) {
+	  // Here's a deleted arc.  Indicate this.
+	  result += "/(...deleted...)";
+	} else {
+	  if (darc->get_parent() != comp->get_next()->get_node() &&
+	      comp->get_next()->get_node() != (Node *)NULL) {
+	    // It's not a deleted arc, but something's broken.
+	    result += "/.../" + format_node_name(darc->get_parent());
+	  }
+	  result += format_arc_name(darc);
+	  result += format_node_name(darc->get_child());
 	}
-	result += format_arc_name(darc);
-	result += format_node_name(darc->get_child());
       }
     }
     return nodes_before + 1;
@@ -2476,7 +2496,6 @@ r_get_net_transitions(const ArcComponent *comp,
 ////////////////////////////////////////////////////////////////////
 string NodePath::
 format_node_name(Node *dnode) const {
-  nassertr(dnode != (Node *)NULL, string());
   if (dnode == (Node *)NULL) {
     return "(NULL)";
   }