aboutsummaryrefslogtreecommitdiff
path: root/src/libutil/closure.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/libutil/closure.hh')
-rw-r--r--src/libutil/closure.hh68
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;
}
}