diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/MappingGraph.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/MappingGraph.cpp index e990dc40a33..5dfae92cecd 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/MappingGraph.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/MappingGraph.cpp @@ -91,11 +91,14 @@ MappingGraph::MappingInputs MappingGraph::getTopMostMechanicalStates( current->accept(visitor); } - for (auto& parent : current->m_parents) + for (auto& weakParent : current->m_parents) { - if (parent->m_pendingCount == 0) + if (const auto parent = weakParent.lock()) { - nodes.push(parent.get()); + if (parent->m_pendingCount == 0) + { + nodes.push(parent.get()); + } } } } @@ -230,11 +233,14 @@ sofa::type::vector MappingGraph::getBottomUpMappingsFrom( current->accept(visitor); - for (auto& parent : current->m_parents) + for (auto& weakParent : current->m_parents) { - if (parent->m_pendingCount == 0) + if (const auto parent = weakParent.lock()) { - nodes.push(parent.get()); + if (parent->m_pendingCount == 0) + { + nodes.push(parent.get()); + } } } } @@ -402,7 +408,7 @@ BaseMappingGraphNode* MappingGraph::findStateNode(core::behavior::BaseMechanical void MappingGraph::addEdge(BaseMappingGraphNode* from, BaseMappingGraphNode* to) { from->m_children.push_back(to->shared_from_this()); - to->m_parents.push_back(from->shared_from_this()); + to->m_parents.push_back(from->weak_from_this()); } } // namespace sofa::simulation diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mappinggraph/BaseMappingGraphNode.cpp b/Sofa/framework/Simulation/Core/src/sofa/simulation/mappinggraph/BaseMappingGraphNode.cpp index 49f5fce593e..ac6cf743837 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mappinggraph/BaseMappingGraphNode.cpp +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mappinggraph/BaseMappingGraphNode.cpp @@ -31,9 +31,10 @@ bool BaseMappingGraphNode::isMapped() const return m_isMapped.value(); } - const auto isMapped = std::any_of(m_parents.begin(), m_parents.end(), [](const SPtr& node) + const auto isMapped = std::any_of(m_parents.begin(), m_parents.end(), [](const std::weak_ptr& weakNode) { - return node->getType() == NodeType::Mapping || node->isMapped(); + const auto node = weakNode.lock(); + return node && (node->getType() == NodeType::Mapping || node->isMapped()); }); m_isMapped = isMapped; diff --git a/Sofa/framework/Simulation/Core/src/sofa/simulation/mappinggraph/BaseMappingGraphNode.h b/Sofa/framework/Simulation/Core/src/sofa/simulation/mappinggraph/BaseMappingGraphNode.h index a76a8b6897f..2a17d61ac4b 100644 --- a/Sofa/framework/Simulation/Core/src/sofa/simulation/mappinggraph/BaseMappingGraphNode.h +++ b/Sofa/framework/Simulation/Core/src/sofa/simulation/mappinggraph/BaseMappingGraphNode.h @@ -70,11 +70,15 @@ class SOFA_SIMULATION_CORE_API BaseMappingGraphNode : public std::enable_shared_ */ bool isMapped() const; - const sofa::type::vector& getParents() const { return m_parents; } + const sofa::type::vector>& getParents() const { return m_parents; } const sofa::type::vector& getChildren() const { return m_children; } private: - sofa::type::vector m_parents; ///< prerequisite nodes (nodes pointing to this one) + /// Prerequisite nodes (nodes pointing to this one). Held as weak_ptr: ownership of every + /// node belongs to MappingGraph::m_allNodes and to the owning parent's m_children; a strong + /// back-reference here would form a parent<->child reference cycle that keeps the whole + /// graph alive forever across rebuilds (MappingGraph::clear() only releases m_allNodes). + sofa::type::vector> m_parents; sofa::type::vector m_children; ///< dependent nodes (nodes pointed from this one) // Mutable counter used during traversal (reset before each traversal).