From a0173a4a4596037bfe7f5866c72f9bd25d424352 Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Sun, 9 Dec 2012 12:06:19 +0100 Subject: Do not presume the use of shared_ptr. --- cells-impl.hpp | 63 +++++++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 29 deletions(-) (limited to 'cells-impl.hpp') diff --git a/cells-impl.hpp b/cells-impl.hpp index 1a9d644..86d7c98 100644 --- a/cells-impl.hpp +++ b/cells-impl.hpp @@ -45,43 +45,45 @@ namespace cells { using namespace dynvars; struct dag_node { - dag_node(std::shared_ptr item_) : item(item_) { } - std::shared_ptr item; + dag_node(observer* item_) : item(item_) { } + observer* item; std::unordered_set incoming_edges; std::unordered_set outgoing_edges; }; struct transaction { - std::unordered_map, std::shared_ptr> dag; + std::unordered_map dag; }; - static thread_local dynvar>> current_dependencies; + static thread_local dynvar> current_dependencies; static thread_local dynvar current_transaction; inline void observer::clear_dependencies() { for (auto const& dep : dependencies) { - dep->remove_dependent(this); + std::shared_ptr sdep = dep.lock(); + if (sdep) { + (*sdep)->remove_dependent(this); + } } dependencies = {}; } - inline void observer::add_dependent(std::shared_ptr dependent) { - dependents.push_front(dependent); + inline void observer::add_dependent(observer* dependent) { + dependents.push_front(dependent->self); } inline void observer::remove_dependent(observer* dependent) { - dependents.remove_if([&](std::weak_ptr const& other) -> bool { - std::shared_ptr other2 = other.lock(); - // note: this should also work for empty other - return (other2.get() == dependent); + dependents.remove_if([&](std::weak_ptr const& other) -> bool { + std::shared_ptr other2 = other.lock(); + return (!other2 || *other2 == dependent); }); } - inline void observer::reset_dependencies(std::forward_list> const& newdeps) { + inline void observer::reset_dependencies(std::forward_list const& newdeps) { clear_dependencies(); - dependencies = newdeps; for (auto const& dep : newdeps) { - dep->add_dependent(shared_from_this()); + dependencies.push_front(dep->self); + dep->add_dependent(this); } } @@ -90,20 +92,23 @@ namespace cells { with_transaction([&]() { this->mark(); }); return; } - std::shared_ptr self = shared_from_this(); - if (current_transaction->dag.find(self) == + if (current_transaction->dag.find(this) == current_transaction->dag.end()) { std::unordered_set incoming_edges; std::unordered_set outgoing_edges; - std::shared_ptr node = std::make_shared(self); - current_transaction->dag[self] = std::shared_ptr(node); - for (std::weak_ptr x : dependents) { - std::shared_ptr px = x.lock(); + dag_node* node = new dag_node(this); + current_transaction->dag[this] = node; + for (auto e = dependents.cbegin(); e != dependents.end(); e++) { + std::weak_ptr const& x = *e; + std::shared_ptr px = x.lock(); if (px) { - px->mark(); - std::shared_ptr xn = current_transaction->dag[px]; - xn->incoming_edges.insert(node.get()); - node->outgoing_edges.insert(xn.get()); + (*px)->mark(); + dag_node* xn = current_transaction->dag[*px]; + xn->incoming_edges.insert(node); + node->outgoing_edges.insert(xn); + } else { + // Purge dead nodes. + dependents.erase(e); } } } @@ -120,9 +125,9 @@ namespace cells { template void cell::update() { T oldval = current_value; - with>, void> + with, void> (current_dependencies, - std::forward_list>(), + std::forward_list(), [=]{ current_value = recompute(current_value); reset_dependencies(*current_dependencies); @@ -132,7 +137,7 @@ namespace cells { template T& cell::get() { if (current_dependencies) { - current_dependencies->push_front(shared_from_this()); + current_dependencies->push_front(this); return current_value; } else { return current_value; @@ -188,7 +193,7 @@ namespace cells { thunk(); //cerr << "; number of affected nodes: " << current_transaction->dag.size() << endl; - std::deque> nodes; + std::deque nodes; // topological sort std::forward_list independent_nodes; @@ -197,7 +202,7 @@ namespace cells { for (auto const& o_and_n : current_transaction->dag) { auto node = o_and_n.second; if (node->incoming_edges.size() == 0) { - independent_nodes.push_front(node.get()); + independent_nodes.push_front(node); } } while (!independent_nodes.empty()) { -- cgit v1.2.3