Nix 2.26.3
Nix, the purely functional package manager; unstable internal interfaces
 
Loading...
Searching...
No Matches
closure.hh
Go to the documentation of this file.
1#pragma once
3
4#include <set>
5#include <future>
6#include "sync.hh"
7
8using std::set;
9
10namespace nix {
11
12template<typename T>
13using GetEdgesAsync = std::function<void(const T &, std::function<void(std::promise<set<T>> &)>)>;
14
15template<typename T>
16void computeClosure(
17 const set<T> startElts,
18 set<T> & res,
19 GetEdgesAsync<T> getEdgesAsync
20)
21{
22 struct State
23 {
24 size_t pending;
25 set<T> & res;
26 std::exception_ptr exc;
27 };
28
29 Sync<State> state_(State{0, res, 0});
30
31 std::function<void(const T &)> enqueue;
32
33 std::condition_variable done;
34
35 enqueue = [&](const T & current) -> void {
36 {
37 auto state(state_.lock());
38 if (state->exc) return;
39 if (!state->res.insert(current).second) return;
40 state->pending++;
41 }
42
43 getEdgesAsync(current, [&](std::promise<set<T>> & prom) {
44 try {
45 auto children = prom.get_future().get();
46 for (auto & child : children)
47 enqueue(child);
48 {
49 auto state(state_.lock());
50 assert(state->pending);
51 if (!--state->pending) done.notify_one();
52 }
53 } catch (...) {
54 auto state(state_.lock());
55 if (!state->exc) state->exc = std::current_exception();
56 assert(state->pending);
57 if (!--state->pending) done.notify_one();
58 };
59 });
60 };
61
62 for (auto & startElt : startElts)
63 enqueue(startElt);
64
65 {
66 auto state(state_.lock());
67 while (state->pending) state.wait(done);
68 if (state->exc) std::rethrow_exception(state->exc);
69 }
70}
71
72}
Strings res
Definition lexer.l:2566
virtual bool set(const std::string &name, const std::string &value)=0
Definition buildenv.cc:13