mirror of
https://github.com/NixOS/nix.git
synced 2025-12-06 17:11:00 +01:00
Make Goal code use abstractions over interations with Worker
Instead of calling `worker.waitForAWhile(shared_from_this())` etc.,
the subclasses of Goal instead call protected functions defined in Goal
that abstract over these.
The code for awaiting has also been heavily simplified.
Instead of calling `addWaitee`, then suspending,
`co_await await(waitees)` is called once, which also handles the suspend.
The end-goal is to remove all manual `co_await Suspend{}`s.
This commit is contained in:
parent
c97f779dbb
commit
36e5aa6c7d
6 changed files with 110 additions and 75 deletions
|
|
@ -132,38 +132,18 @@ void addToWeakGoals(WeakGoals & goals, GoalPtr p)
|
|||
goals.insert(p);
|
||||
}
|
||||
|
||||
|
||||
void Goal::addWaitee(GoalPtr waitee)
|
||||
Co Goal::await(Goals new_waitees)
|
||||
{
|
||||
waitees.insert(waitee);
|
||||
addToWeakGoals(waitee->waiters, shared_from_this());
|
||||
}
|
||||
|
||||
|
||||
void Goal::waiteeDone(GoalPtr waitee, ExitCode result)
|
||||
{
|
||||
assert(waitees.count(waitee));
|
||||
waitees.erase(waitee);
|
||||
|
||||
trace(fmt("waitee '%s' done; %d left", waitee->name, waitees.size()));
|
||||
|
||||
if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++nrFailed;
|
||||
|
||||
if (result == ecNoSubstituters) ++nrNoSubstituters;
|
||||
|
||||
if (result == ecIncompleteClosure) ++nrIncompleteClosure;
|
||||
|
||||
if (waitees.empty() || (result == ecFailed && !settings.keepGoing)) {
|
||||
|
||||
/* If we failed and keepGoing is not set, we remove all
|
||||
remaining waitees. */
|
||||
for (auto & goal : waitees) {
|
||||
goal->waiters.extract(shared_from_this());
|
||||
assert(waitees.empty());
|
||||
if (!new_waitees.empty()) {
|
||||
waitees = std::move(new_waitees);
|
||||
for (auto waitee : waitees) {
|
||||
addToWeakGoals(waitee->waiters, shared_from_this());
|
||||
}
|
||||
waitees.clear();
|
||||
|
||||
worker.wakeUp(shared_from_this());
|
||||
co_await Suspend{};
|
||||
assert(waitees.empty());
|
||||
}
|
||||
co_return Return{};
|
||||
}
|
||||
|
||||
Goal::Done Goal::amDone(ExitCode result, std::optional<Error> ex)
|
||||
|
|
@ -183,7 +163,32 @@ Goal::Done Goal::amDone(ExitCode result, std::optional<Error> ex)
|
|||
|
||||
for (auto & i : waiters) {
|
||||
GoalPtr goal = i.lock();
|
||||
if (goal) goal->waiteeDone(shared_from_this(), result);
|
||||
if (goal) {
|
||||
auto me = shared_from_this();
|
||||
assert(goal->waitees.count(me));
|
||||
goal->waitees.erase(me);
|
||||
|
||||
goal->trace(fmt("waitee '%s' done; %d left", name, goal->waitees.size()));
|
||||
|
||||
if (result == ecFailed || result == ecNoSubstituters || result == ecIncompleteClosure) ++goal->nrFailed;
|
||||
|
||||
if (result == ecNoSubstituters) ++goal->nrNoSubstituters;
|
||||
|
||||
if (result == ecIncompleteClosure) ++goal->nrIncompleteClosure;
|
||||
|
||||
if (goal->waitees.empty()) {
|
||||
worker.wakeUp(goal);
|
||||
} else if (result == ecFailed && !settings.keepGoing) {
|
||||
/* If we failed and keepGoing is not set, we remove all
|
||||
remaining waitees. */
|
||||
for (auto & g : goal->waitees) {
|
||||
g->waiters.extract(goal);
|
||||
}
|
||||
goal->waitees.clear();
|
||||
|
||||
worker.wakeUp(goal);
|
||||
}
|
||||
}
|
||||
}
|
||||
waiters.clear();
|
||||
worker.removeGoal(shared_from_this());
|
||||
|
|
@ -215,5 +220,22 @@ void Goal::work()
|
|||
assert(top_co || exitCode != ecBusy);
|
||||
}
|
||||
|
||||
Goal::Co Goal::yield() {
|
||||
worker.wakeUp(shared_from_this());
|
||||
co_await Suspend{};
|
||||
co_return Return{};
|
||||
}
|
||||
|
||||
Goal::Co Goal::waitForAWhile() {
|
||||
worker.waitForAWhile(shared_from_this());
|
||||
co_await Suspend{};
|
||||
co_return Return{};
|
||||
}
|
||||
|
||||
Goal::Co Goal::waitForBuildSlot() {
|
||||
worker.waitForBuildSlot(shared_from_this());
|
||||
co_await Suspend{};
|
||||
co_return Return{};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue