move the destructor implementation from .h to -inst.h
parent
46c311b5b9
commit
36e9d4aaed
|
@ -26,6 +26,7 @@
|
||||||
#include <gtsam/base/timing.h>
|
#include <gtsam/base/timing.h>
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -178,6 +179,45 @@ namespace gtsam {
|
||||||
*this = other;
|
*this = other;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
/** Destructor
|
||||||
|
* Using default destructor causes stack overflow for large trees due to recursive destruction of nodes;
|
||||||
|
* so we manually decrease the reference count of each node in the tree through a BFS, and the nodes with
|
||||||
|
* reference count 0 will be deleted. Please see [PR-1441](https://github.com/borglab/gtsam/pull/1441) for more details.
|
||||||
|
*/
|
||||||
|
template<class CLIQUE>
|
||||||
|
BayesTree<CLIQUE>::~BayesTree() {
|
||||||
|
/* Because tree nodes are hold by both root_ and nodes_, we need to clear nodes_ manually first and
|
||||||
|
* reduce the reference count of each node by 1. Otherwise, the nodes will not be properly deleted
|
||||||
|
* during the BFS process.
|
||||||
|
*/
|
||||||
|
nodes_.clear();
|
||||||
|
for (auto&& root: roots_) {
|
||||||
|
std::queue<sharedClique> bfs_queue;
|
||||||
|
|
||||||
|
// first, move the root to the queue
|
||||||
|
bfs_queue.push(root);
|
||||||
|
root = nullptr; // now the root node is owned by the queue
|
||||||
|
|
||||||
|
// do a BFS on the tree, for each node, add its children to the queue, and then delete it from the queue
|
||||||
|
// So if the reference count of the node is 1, it will be deleted, and because its children are in the queue,
|
||||||
|
// the deletion of the node will not trigger a recursive deletion of the children.
|
||||||
|
while (!bfs_queue.empty()) {
|
||||||
|
// move the ownership of the front node from the queue to the current variable
|
||||||
|
auto current = bfs_queue.front();
|
||||||
|
bfs_queue.pop();
|
||||||
|
|
||||||
|
// add the children of the current node to the queue, so that the queue will also own the children nodes.
|
||||||
|
for (auto child: current->children) {
|
||||||
|
bfs_queue.push(child);
|
||||||
|
} // leaving the scope of current will decrease the reference count of the current node by 1, and if the reference count is 0,
|
||||||
|
// the node will be deleted. Because the children are in the queue, the deletion of the node will not trigger a recursive
|
||||||
|
// deletion of the children.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
namespace {
|
namespace {
|
||||||
template<typename NODE>
|
template<typename NODE>
|
||||||
|
|
|
@ -27,7 +27,6 @@
|
||||||
#include <gtsam/base/FastVector.h>
|
#include <gtsam/base/FastVector.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -112,30 +111,11 @@ namespace gtsam {
|
||||||
/** Copy constructor */
|
/** Copy constructor */
|
||||||
BayesTree(const This& other);
|
BayesTree(const This& other);
|
||||||
|
|
||||||
~BayesTree() {
|
|
||||||
nodes_.clear(); // clear the map manually, as we cannot control the order of destruction in the map
|
|
||||||
for (auto&& root: roots_) {
|
|
||||||
std::queue<sharedClique> bfs_queue;
|
|
||||||
|
|
||||||
// first, move the root to the queue
|
|
||||||
bfs_queue.push(root);
|
|
||||||
root = nullptr;
|
|
||||||
|
|
||||||
// do a BFS on the tree, for each node, add its children to the queue, and then delete it from the queue
|
|
||||||
// So if the reference count of the node is 1, it will be deleted, and because its children are in the queue,
|
|
||||||
// the deletion of the node will not trigger a recursive deletion of the children.
|
|
||||||
while (!bfs_queue.empty()) {
|
|
||||||
auto current = bfs_queue.front();
|
|
||||||
bfs_queue.pop();
|
|
||||||
for (auto child: current->children) {
|
|
||||||
bfs_queue.push(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/** Destructor */
|
||||||
|
~BayesTree();
|
||||||
|
|
||||||
/** Assignment operator */
|
/** Assignment operator */
|
||||||
This& operator=(const This& other);
|
This& operator=(const This& other);
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#ifdef GTSAM_USE_TBB
|
#ifdef GTSAM_USE_TBB
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#endif
|
#endif
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
namespace gtsam {
|
namespace gtsam {
|
||||||
|
|
||||||
|
@ -99,6 +100,41 @@ void ClusterTree<GRAPH>::print(const std::string& s, const KeyFormatter& keyForm
|
||||||
treeTraversal::PrintForest(*this, s, keyFormatter);
|
treeTraversal::PrintForest(*this, s, keyFormatter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
/* Destructor.
|
||||||
|
* Using default destructor causes stack overflow for large trees due to recursive destruction of nodes;
|
||||||
|
* so we manually decrease the reference count of each node in the tree through a BFS, and the nodes with
|
||||||
|
* reference count 0 will be deleted. Please see [PR-1441](https://github.com/borglab/gtsam/pull/1441) for more details.
|
||||||
|
*/
|
||||||
|
template <class GRAPH>
|
||||||
|
ClusterTree<GRAPH>::~ClusterTree() {
|
||||||
|
// For each tree, we first move the root into a queue; then we do a BFS on the tree with the queue;
|
||||||
|
|
||||||
|
for (auto&& root : roots_) {
|
||||||
|
std::queue<sharedNode> bfs_queue;
|
||||||
|
// first, move the root to the queue
|
||||||
|
bfs_queue.push(root);
|
||||||
|
root = nullptr; // now the root node is owned by the queue
|
||||||
|
|
||||||
|
// for each node iterated, if its reference count is 1, it will be deleted while its children are still in the queue.
|
||||||
|
// so that the recursive deletion will not happen.
|
||||||
|
while (!bfs_queue.empty()) {
|
||||||
|
// move the ownership of the front node from the queue to the current variable
|
||||||
|
auto node = bfs_queue.front();
|
||||||
|
bfs_queue.pop();
|
||||||
|
|
||||||
|
// add the children of the current node to the queue, so that the queue will also own the children nodes.
|
||||||
|
for (auto child : node->children) {
|
||||||
|
bfs_queue.push(child);
|
||||||
|
} // leaving the scope of current will decrease the reference count of the current node by 1, and if the reference count is 0,
|
||||||
|
// the node will be deleted. Because the children are in the queue, the deletion of the node will not trigger a recursive
|
||||||
|
// deletion of the children.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template <class GRAPH>
|
template <class GRAPH>
|
||||||
ClusterTree<GRAPH>& ClusterTree<GRAPH>::operator=(const This& other) {
|
ClusterTree<GRAPH>& ClusterTree<GRAPH>::operator=(const This& other) {
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <queue>
|
|
||||||
#include <gtsam/base/Testable.h>
|
#include <gtsam/base/Testable.h>
|
||||||
#include <gtsam/base/FastVector.h>
|
#include <gtsam/base/FastVector.h>
|
||||||
#include <gtsam/inference/Ordering.h>
|
#include <gtsam/inference/Ordering.h>
|
||||||
|
@ -165,27 +164,10 @@ class ClusterTree {
|
||||||
return *(roots_[i]);
|
return *(roots_[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ClusterTree() {
|
|
||||||
// use default destructor which recursively deletes all nodes with shared_ptr causes stack overflow.
|
|
||||||
// so for each tree, we first move the root into a queue; then we do a BFS on the tree with the queue;
|
|
||||||
// for each node iterated, if its reference count is 1, it will be deleted while its children are still in the queue.
|
|
||||||
// so that the recursive deletion will not happen.
|
|
||||||
for (auto&& root : roots_) {
|
|
||||||
std::queue<sharedNode> bfs_queue;
|
|
||||||
bfs_queue.push(root);
|
|
||||||
root = nullptr;
|
|
||||||
while (!bfs_queue.empty()) {
|
|
||||||
auto node = bfs_queue.front();
|
|
||||||
bfs_queue.pop();
|
|
||||||
for (auto child : node->children) {
|
|
||||||
bfs_queue.push(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
~ClusterTree();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// @name Details
|
/// @name Details
|
||||||
/// @{
|
/// @{
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
#include <gtsam/base/timing.h>
|
#include <gtsam/base/timing.h>
|
||||||
#include <gtsam/base/treeTraversal-inst.h>
|
#include <gtsam/base/treeTraversal-inst.h>
|
||||||
|
@ -180,6 +181,43 @@ namespace gtsam {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ************************************************************************* */
|
||||||
|
|
||||||
|
/** Destructor
|
||||||
|
* Using default destructor causes stack overflow for large trees due to recursive destruction of nodes;
|
||||||
|
* so we manually decrease the reference count of each node in the tree through a BFS, and the nodes with
|
||||||
|
* reference count 0 will be deleted. Please see [PR-1441](https://github.com/borglab/gtsam/pull/1441) for more details.
|
||||||
|
*/
|
||||||
|
template<class BAYESNET, class GRAPH>
|
||||||
|
EliminationTree<BAYESNET,GRAPH>::~EliminationTree()
|
||||||
|
{
|
||||||
|
// For each tree, we first move the root into a queue; then we do a BFS on the tree with the queue;
|
||||||
|
|
||||||
|
for (auto&& root : roots_) {
|
||||||
|
std::queue<sharedNode> bfs_queue;
|
||||||
|
|
||||||
|
// first, move the root to the queue
|
||||||
|
bfs_queue.push(root);
|
||||||
|
root = nullptr; // now the root node is owned by the queue
|
||||||
|
|
||||||
|
// for each node iterated, if its reference count is 1, it will be deleted while its children are still in the queue.
|
||||||
|
// so that the recursive deletion will not happen.
|
||||||
|
while (!bfs_queue.empty()) {
|
||||||
|
// move the ownership of the front node from the queue to the current variable
|
||||||
|
auto node = bfs_queue.front();
|
||||||
|
bfs_queue.pop();
|
||||||
|
|
||||||
|
// add the children of the current node to the queue, so that the queue will also own the children nodes.
|
||||||
|
for (auto&& child : node->children) {
|
||||||
|
bfs_queue.push(child);
|
||||||
|
} // leaving the scope of current will decrease the reference count of the current node by 1, and if the reference count is 0,
|
||||||
|
// the node will be deleted. Because the children are in the queue, the deletion of the node will not trigger a recursive
|
||||||
|
// deletion of the children.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
template<class BAYESNET, class GRAPH>
|
template<class BAYESNET, class GRAPH>
|
||||||
std::pair<std::shared_ptr<BAYESNET>, std::shared_ptr<GRAPH> >
|
std::pair<std::shared_ptr<BAYESNET>, std::shared_ptr<GRAPH> >
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <queue>
|
|
||||||
|
|
||||||
#include <gtsam/base/Testable.h>
|
#include <gtsam/base/Testable.h>
|
||||||
#include <gtsam/base/FastVector.h>
|
#include <gtsam/base/FastVector.h>
|
||||||
|
@ -119,24 +118,7 @@ namespace gtsam {
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~EliminationTree() {
|
~EliminationTree();
|
||||||
// use default destructor which recursively deletes all nodes with shared_ptr causes stack overflow.
|
|
||||||
// so for each tree, we first move the root into a queue; then we do a BFS on the tree with the queue;
|
|
||||||
// for each node iterated, if its reference count is 1, it will be deleted while its children are still in the queue.
|
|
||||||
// so that the recursive deletion will not happen.
|
|
||||||
for (auto&& root : roots_) {
|
|
||||||
std::queue<sharedNode> bfs_queue;
|
|
||||||
bfs_queue.push(root);
|
|
||||||
root = nullptr;
|
|
||||||
while (!bfs_queue.empty()) {
|
|
||||||
auto node = bfs_queue.front();
|
|
||||||
bfs_queue.pop();
|
|
||||||
for (auto&& child : node->children) {
|
|
||||||
bfs_queue.push(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// @name Standard Interface
|
/// @name Standard Interface
|
||||||
/// @{
|
/// @{
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue