diff options
Diffstat (limited to 'src/libutil/closure.hh')
-rw-r--r-- | src/libutil/closure.hh | 68 |
1 files changed, 14 insertions, 54 deletions
diff --git a/src/libutil/closure.hh b/src/libutil/closure.hh index 16e3b93e4..146931fc8 100644 --- a/src/libutil/closure.hh +++ b/src/libutil/closure.hh @@ -1,72 +1,32 @@ #pragma once ///@file +#include <functional> #include <set> -#include <future> -#include "sync.hh" - -using std::set; namespace nix { template<typename T> -using GetEdgesAsync = std::function<void(const T &, std::function<void(std::promise<set<T>> &)>)>; - -template<typename T> -void computeClosure( - const set<T> startElts, - set<T> & res, - GetEdgesAsync<T> getEdgesAsync +std::set<T> computeClosure( + std::set<T> startElts, + std::function<std::set<T>(const T &)> getEdges ) { - struct State - { - size_t pending; - set<T> & res; - std::exception_ptr exc; - }; - - Sync<State> state_(State{0, res, 0}); + std::set<T> res, queue = std::move(startElts); - std::function<void(const T &)> enqueue; + while (!queue.empty()) { + std::set<T> next; - std::condition_variable done; - - enqueue = [&](const T & current) -> void { - { - auto state(state_.lock()); - if (state->exc) return; - if (!state->res.insert(current).second) return; - state->pending++; + for (auto & e : queue) { + if (res.insert(e).second) { + next.merge(getEdges(e)); + } } - getEdgesAsync(current, [&](std::promise<set<T>> & prom) { - try { - auto children = prom.get_future().get(); - for (auto & child : children) - enqueue(child); - { - auto state(state_.lock()); - assert(state->pending); - if (!--state->pending) done.notify_one(); - } - } catch (...) { - auto state(state_.lock()); - if (!state->exc) state->exc = std::current_exception(); - assert(state->pending); - if (!--state->pending) done.notify_one(); - }; - }); - }; - - for (auto & startElt : startElts) - enqueue(startElt); - - { - auto state(state_.lock()); - while (state->pending) state.wait(done); - if (state->exc) std::rethrow_exception(state->exc); + queue = std::move(next); } + + return res; } } |