xbt_assert(parent_state_ != nullptr, "Attempting to construct a wakeup tree for the root state "
"(or what appears to be, rather for state without a parent defined)");
const auto p = parent_state_->get_transition_out()->aid_;
- const auto branch = std::find_if(wakeup_tree_.begin(), wakeup_tree_.end(), [=](const odpor::WakeupTreeNode* node) {
- return node->is_single_process() && node->get_first_actor() == p;
- });
- xbt_assert(branch != wakeup_tree_.end(),
+ const auto branch = std::find_if(
+ parent_state_->wakeup_tree_.begin(), parent_state_->wakeup_tree_.end(),
+ [=](const odpor::WakeupTreeNode* node) { return node->is_single_process() && node->get_first_actor() == p; });
+ xbt_assert(branch != parent_state_->wakeup_tree_.end(),
"Attempted to create a subtree from the wakeup tree of the parent "
"state using actor `%ld`, but no such subtree could be found. "
"This implies that the wakeup tree management is broken, "
return get_sequence().front()->aid_;
}
+void WakeupTreeNode::add_child(WakeupTreeNode* node)
+{
+ this->children_.push_back(node);
+ node->parent_ = this;
+}
+
+WakeupTreeNode::~WakeupTreeNode()
+{
+ if (parent_ != nullptr) {
+ // TODO: We can probably be more clever here: when
+ // we add the child to a node, we could perhaps
+ // try instead to keep a reference to position of the
+ // child in the list of the parent.
+ parent_->children_.remove(this);
+ }
+}
+
WakeupTree::WakeupTree() : WakeupTree(std::unique_ptr<WakeupTreeNode>(new WakeupTreeNode({}))) {}
WakeupTree::WakeupTree(std::unique_ptr<WakeupTreeNode> root) : root_(root.get())
{
throw std::invalid_argument("Selecting subtrees is only defined for single-process nodes");
}
- const aid_t p = (*(root->get_sequence().begin()))->aid_;
+ const aid_t p = root->get_first_actor();
// Perform a BFS search to perform a deep copy of the portion
// of the tree underneath and including `root`. Note that `root`
// is contained within the context of a *different* wakeup tree;
// hence, we have to be careful to update each node's children
// appropriately
- auto subtree = WakeupTree();
- WakeupTreeNode* root_equivalent = subtree.make_node(root->get_sequence());
+ auto subtree = WakeupTree();
- std::list<std::pair<WakeupTreeNode*, WakeupTreeNode*>> frontier{std::make_pair(root, root_equivalent)};
+ std::list<std::pair<WakeupTreeNode*, WakeupTreeNode*>> frontier{std::make_pair(root, subtree.root_)};
while (not frontier.empty()) {
auto [node_in_other_tree, subtree_equivalent] = frontier.front();
frontier.pop_front();
p_w.pop_front();
WakeupTreeNode* child_equivalent = subtree.make_node(p_w);
- subtree_equivalent->add_child(child_equivalent);
frontier.push_back(std::make_pair(child_in_other_tree, child_equivalent));
}
}
"that is not contained in this wakeup tree");
}
- std::list<WakeupTreeNode*> subtree_contents;
+ std::list<WakeupTreeNode*> subtree_contents{root};
std::list<WakeupTreeNode*> frontier{root};
while (not frontier.empty()) {
auto node = frontier.front();
}
// After having found each node with BFS, now we can
- // remove them. This prevents the "joys" iteration during mutation
+ // remove them. This prevents the "joys" of iteration during mutation
for (WakeupTreeNode* node_to_remove : subtree_contents) {
this->remove_node(node_to_remove);
}
#include "src/mc/explo/odpor/odpor_forward.hpp"
#include <memory>
+#include <optional>
#include <unordered_map>
namespace simgrid::mc::odpor {
explicit WakeupTreeNode(const PartialExecution& u) : seq_(u) {}
explicit WakeupTreeNode(PartialExecution&& u) : seq_(std::move(u)) {}
+ WakeupTreeNode* parent_ = nullptr;
+
/** An ordered list of children of for this node in the tree */
std::list<WakeupTreeNode*> children_;
friend WakeupTreeIterator;
public:
+ ~WakeupTreeNode();
WakeupTreeNode(const WakeupTreeNode&) = delete;
WakeupTreeNode(WakeupTreeNode&&) = default;
WakeupTreeNode& operator=(const WakeupTreeNode&) = delete;
aid_t get_first_actor() const;
/** Insert a node `node` as a new child of this node */
- void add_child(WakeupTreeNode* node) { this->children_.push_back(node); }
+ void add_child(WakeupTreeNode* node);
};
class WakeupTree {