From 020ea8c8fc03df855a7014328e2ce2528e799d93 Mon Sep 17 00:00:00 2001 From: eldritch horrors Date: Wed, 22 Jan 2025 02:59:14 +0100 Subject: [PATCH] libutil: add async base header currently this header only contains TRY_AWAIT, and it's public version LIX_TRY_AWAIT. the former is for use in our cpp files only, the latter may be used anywhere. we don't expose TRY_AWAIT unconditionally due to it not being namespaced according to usual rules of macro naming, i.e. exposing it may litter user macro namespaces unnecessarily. hiding our internal version is achieved using a new define that's not set through pkg-config or other means. (we could also add a private header that we simply do not install, but that gets rather messy rather very quickly) Change-Id: I372b1a414487dd03cfbfc620b3148a6c6e56ca3f --- lix/libstore/build/derivation-goal.cc | 11 ++++---- .../build/drv-output-substitution-goal.cc | 3 +- lix/libstore/build/substitution-goal.cc | 3 +- lix/libutil/async.hh | 28 +++++++++++++++++++ lix/libutil/meson.build | 1 + meson.build | 9 ++++++ 6 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 lix/libutil/async.hh diff --git a/lix/libstore/build/derivation-goal.cc b/lix/libstore/build/derivation-goal.cc index 08ffe7750..b261ee027 100644 --- a/lix/libstore/build/derivation-goal.cc +++ b/lix/libstore/build/derivation-goal.cc @@ -1,4 +1,5 @@ #include "lix/libstore/build/derivation-goal.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/file-system.hh" #include "lix/libstore/build/hook-instance.hh" #include "lix/libstore/build/worker.hh" @@ -176,7 +177,7 @@ try { co_return co_await loadDerivation(); } - (co_await waitForGoals(worker.goalFactory().makePathSubstitutionGoal(drvPath))).value(); + TRY_AWAIT(waitForGoals(worker.goalFactory().makePathSubstitutionGoal(drvPath))); co_return co_await loadDerivation(); } catch (...) { co_return result::current_exception(); @@ -302,7 +303,7 @@ try { } if (!dependencies.empty()) { /* to prevent hang (no wake-up event) */ - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); } co_return co_await outputsSubstitutionTried(); } catch (...) { @@ -447,7 +448,7 @@ try { } if (!dependencies.empty()) {/* to prevent hang (no wake-up event) */ - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); } co_return co_await inputsRealised(); } catch (...) { @@ -513,7 +514,7 @@ try { co_return done(BuildResult::AlreadyValid, assertPathValidity()); } - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); co_return co_await closureRepaired(); } catch (...) { co_return result::current_exception(); @@ -618,7 +619,7 @@ try { pathResolved, wantedOutputs, buildMode); resolvedDrvGoal = dependency.first; - (co_await waitForGoals(std::move(dependency))).value(); + TRY_AWAIT(waitForGoals(std::move(dependency))); co_return co_await resolvedFinished(); } diff --git a/lix/libstore/build/drv-output-substitution-goal.cc b/lix/libstore/build/drv-output-substitution-goal.cc index 9d33e9b31..ace2f5161 100644 --- a/lix/libstore/build/drv-output-substitution-goal.cc +++ b/lix/libstore/build/drv-output-substitution-goal.cc @@ -1,5 +1,6 @@ #include "lix/libstore/build/drv-output-substitution-goal.hh" #include "lix/libstore/build-result.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/finally.hh" #include "lix/libstore/build/worker.hh" #include "lix/libstore/build/substitution-goal.hh" @@ -126,7 +127,7 @@ try { dependencies.add(worker.goalFactory().makePathSubstitutionGoal(outputInfo->outPath)); if (!dependencies.empty()) { - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); } co_return co_await outPathValid(); } catch (...) { diff --git a/lix/libstore/build/substitution-goal.cc b/lix/libstore/build/substitution-goal.cc index 50ee7ff7f..2501495f9 100644 --- a/lix/libstore/build/substitution-goal.cc +++ b/lix/libstore/build/substitution-goal.cc @@ -1,6 +1,7 @@ #include "lix/libstore/build/worker.hh" #include "lix/libstore/build/substitution-goal.hh" #include "lix/libstore/nar-info.hh" +#include "lix/libutil/async.hh" #include "lix/libutil/signals.hh" #include "lix/libutil/finally.hh" #include @@ -166,7 +167,7 @@ try { dependencies.add(worker.goalFactory().makePathSubstitutionGoal(i)); if (!dependencies.empty()) {/* to prevent hang (no wake-up event) */ - (co_await waitForGoals(dependencies.releaseAsArray())).value(); + TRY_AWAIT(waitForGoals(dependencies.releaseAsArray())); } co_return co_await referencesValid(); } catch (...) { diff --git a/lix/libutil/async.hh b/lix/libutil/async.hh new file mode 100644 index 000000000..72dd644fe --- /dev/null +++ b/lix/libutil/async.hh @@ -0,0 +1,28 @@ +#pragma once +///@file + +#include "lix/libutil/result.hh" + +namespace nix { +namespace detail { +inline void materializeResult(Result r) +{ + r.value(); +} + +template +inline T materializeResult(Result r) +{ + return std::move(r.value()); +} +} +} + +// force materialization of the value. result::value() returns only an rvalue reference +// and is thus unsuitable for use in e.g. range for without materialization. ideally we +// would wrap the expression in `auto()`, but apple clang fails when given `auto(void)` +#define LIX_TRY_AWAIT(...) (::nix::detail::materializeResult(co_await (__VA_ARGS__))) + +#if LIX_UR_COMPILER_UWU +# define TRY_AWAIT LIX_TRY_AWAIT +#endif diff --git a/lix/libutil/meson.build b/lix/libutil/meson.build index 1f8904b3b..4a04698cb 100644 --- a/lix/libutil/meson.build +++ b/lix/libutil/meson.build @@ -55,6 +55,7 @@ libutil_headers = files( 'args/root.hh', 'args.hh', 'async-collect.hh', + 'async.hh', 'async-semaphore.hh', 'backed-string-view.hh', 'box_ptr.hh', diff --git a/meson.build b/meson.build index dab2e063f..88130c9ca 100644 --- a/meson.build +++ b/meson.build @@ -138,6 +138,15 @@ endif cxx = meson.get_compiler('cpp') +# tag define to tell us we are compiling lix itself and can thus make +# non-namespaced aliases of a utility defines visible. this spares us +# writing LIX_TRY_AWAIT, LIX_RUN_ASYNC_IN, and others in our own code +# without being forced to hide the headers we take these defines from +add_project_arguments( + '-DLIX_UR_COMPILER_UWU', + language : 'cpp', +) + # clangd breaks when GCC is using precompiled headers lmao # https://git.lix.systems/lix-project/lix/issues/374