aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/misc.cc32
-rw-r--r--src/libstore/realisation.cc15
-rw-r--r--src/libutil/closure.hh68
-rw-r--r--tests/unit/libutil/closure.cc35
4 files changed, 27 insertions, 123 deletions
diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc
index c8646083b..22f6b67ee 100644
--- a/src/libstore/misc.cc
+++ b/src/libstore/misc.cc
@@ -14,10 +14,9 @@ namespace nix {
void Store::computeFSClosure(const StorePathSet & startPaths,
StorePathSet & paths_, bool flipDirection, bool includeOutputs, bool includeDerivers)
{
- std::function<std::set<StorePath>(const StorePath & path, std::future<ref<const ValidPathInfo>> &)> queryDeps;
+ std::function<std::set<StorePath>(const StorePath & path, ref<const ValidPathInfo>)> queryDeps;
if (flipDirection)
- queryDeps = [&](const StorePath& path,
- std::future<ref<const ValidPathInfo>> & fut) {
+ queryDeps = [&](const StorePath& path, ref<const ValidPathInfo>) {
StorePathSet res;
StorePathSet referrers;
queryReferrers(path, referrers);
@@ -36,10 +35,8 @@ void Store::computeFSClosure(const StorePathSet & startPaths,
return res;
};
else
- queryDeps = [&](const StorePath& path,
- std::future<ref<const ValidPathInfo>> & fut) {
+ queryDeps = [&](const StorePath& path, ref<const ValidPathInfo> info) {
StorePathSet res;
- auto info = fut.get();
for (auto& ref : info->references)
if (ref != path)
res.insert(ref);
@@ -54,24 +51,11 @@ void Store::computeFSClosure(const StorePathSet & startPaths,
return res;
};
- computeClosure<StorePath>(
- startPaths, paths_,
- [&](const StorePath& path,
- std::function<void(std::promise<std::set<StorePath>>&)>
- processEdges) {
- std::promise<std::set<StorePath>> promise;
- std::function<void(std::future<ref<const ValidPathInfo>>)>
- getDependencies =
- [&](std::future<ref<const ValidPathInfo>> fut) {
- try {
- promise.set_value(queryDeps(path, fut));
- } catch (...) {
- promise.set_exception(std::current_exception());
- }
- };
- queryPathInfo(path, getDependencies);
- processEdges(promise);
- });
+ paths_.merge(computeClosure<StorePath>(
+ startPaths,
+ [&](const StorePath& path) -> std::set<StorePath> {
+ return queryDeps(path, queryPathInfo(path));
+ }));
}
void Store::computeFSClosure(const StorePath & startPath,
diff --git a/src/libstore/realisation.cc b/src/libstore/realisation.cc
index 93ddb5b20..50c911da0 100644
--- a/src/libstore/realisation.cc
+++ b/src/libstore/realisation.cc
@@ -43,20 +43,7 @@ void Realisation::closure(Store & store, const std::set<Realisation> & startOutp
return res;
};
- computeClosure<Realisation>(
- startOutputs, res,
- [&](const Realisation& current,
- std::function<void(std::promise<std::set<Realisation>>&)>
- processEdges) {
- std::promise<std::set<Realisation>> promise;
- try {
- auto res = getDeps(current);
- promise.set_value(res);
- } catch (...) {
- promise.set_exception(std::current_exception());
- }
- return processEdges(promise);
- });
+ res.merge(computeClosure<Realisation>(startOutputs, getDeps));
}
nlohmann::json Realisation::toJSON() const {
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;
}
}
diff --git a/tests/unit/libutil/closure.cc b/tests/unit/libutil/closure.cc
index 7597e7807..b4eaad6f9 100644
--- a/tests/unit/libutil/closure.cc
+++ b/tests/unit/libutil/closure.cc
@@ -16,15 +16,11 @@ map<string, set<string>> testGraph = {
};
TEST(closure, correctClosure) {
- set<string> aClosure;
set<string> expectedClosure = {"A", "B", "C", "F", "G"};
- computeClosure<string>(
+ set<string> aClosure = computeClosure<string>(
{"A"},
- aClosure,
- [&](const string currentNode, function<void(promise<set<string>> &)> processEdges) {
- promise<set<string>> promisedNodes;
- promisedNodes.set_value(testGraph[currentNode]);
- processEdges(promisedNodes);
+ [&](const string currentNode) {
+ return testGraph[currentNode];
}
);
@@ -33,12 +29,10 @@ TEST(closure, correctClosure) {
TEST(closure, properlyHandlesDirectExceptions) {
struct TestExn {};
- set<string> aClosure;
EXPECT_THROW(
computeClosure<string>(
{"A"},
- aClosure,
- [&](const string currentNode, function<void(promise<set<string>> &)> processEdges) {
+ [&](const string currentNode) -> set<string> {
throw TestExn();
}
),
@@ -46,25 +40,4 @@ TEST(closure, properlyHandlesDirectExceptions) {
);
}
-TEST(closure, properlyHandlesExceptionsInPromise) {
- struct TestExn {};
- set<string> aClosure;
- EXPECT_THROW(
- computeClosure<string>(
- {"A"},
- aClosure,
- [&](const string currentNode, function<void(promise<set<string>> &)> processEdges) {
- promise<set<string>> promise;
- try {
- throw TestExn();
- } catch (...) {
- promise.set_exception(std::current_exception());
- }
- processEdges(promise);
- }
- ),
- TestExn
- );
-}
-
}