mirror of
https://github.com/NixOS/nix
synced 2025-07-06 05:01:48 +02:00
Add a ListBuilder helper for constructing list values
Previously, `state.mkList()` would set the type of the value to tList and allocate the list vector, but it would not initialize the values in the list. This has two problems: * If an exception occurs, the list is left in an undefined state. * More importantly, for multithreaded evaluation, if a value transitions from thunk to non-thunk, it should be final (i.e. other threads should be able to access the value safely). To address this, there now is a `ListBuilder` class (analogous to `BindingsBuilder`) to build the list vector prior to the call to `Value::mkList()`. Typical usage: auto list = state.buildList(size); for (auto & v : list) v = ... set value ...; vRes.mkList(list);
This commit is contained in:
parent
bff5c94184
commit
fecff520d7
10 changed files with 228 additions and 157 deletions
|
@ -172,7 +172,7 @@ static void loadSourceExpr(EvalState & state, const SourcePath & path, Value & v
|
|||
directory). */
|
||||
else if (st.type == InputAccessor::tDirectory) {
|
||||
auto attrs = state.buildBindings(maxAttrs);
|
||||
state.mkList(attrs.alloc("_combineChannels"), 0);
|
||||
attrs.insert(state.symbols.create("_combineChannels"), &state.vEmptyList);
|
||||
StringSet seen;
|
||||
getAllExprs(state, path, seen, attrs);
|
||||
v.mkAttrs(attrs);
|
||||
|
|
|
@ -49,10 +49,8 @@ bool createUserEnv(EvalState & state, PackageInfos & elems,
|
|||
|
||||
/* Construct the whole top level derivation. */
|
||||
StorePathSet references;
|
||||
Value manifest;
|
||||
state.mkList(manifest, elems.size());
|
||||
size_t n = 0;
|
||||
for (auto & i : elems) {
|
||||
auto list = state.buildList(elems.size());
|
||||
for (const auto & [n, i] : enumerate(elems)) {
|
||||
/* Create a pseudo-derivation containing the name, system,
|
||||
output paths, and optionally the derivation path, as well
|
||||
as the meta attributes. */
|
||||
|
@ -72,10 +70,9 @@ bool createUserEnv(EvalState & state, PackageInfos & elems,
|
|||
attrs.alloc(state.sDrvPath).mkString(state.store->printStorePath(*drvPath));
|
||||
|
||||
// Copy each output meant for installation.
|
||||
auto & vOutputs = attrs.alloc(state.sOutputs);
|
||||
state.mkList(vOutputs, outputs.size());
|
||||
auto outputsList = state.buildList(outputs.size());
|
||||
for (const auto & [m, j] : enumerate(outputs)) {
|
||||
(vOutputs.listElems()[m] = state.allocValue())->mkString(j.first);
|
||||
(outputsList[m] = state.allocValue())->mkString(j.first);
|
||||
auto outputAttrs = state.buildBindings(2);
|
||||
outputAttrs.alloc(state.sOutPath).mkString(state.store->printStorePath(*j.second));
|
||||
attrs.alloc(j.first).mkAttrs(outputAttrs);
|
||||
|
@ -87,6 +84,7 @@ bool createUserEnv(EvalState & state, PackageInfos & elems,
|
|||
|
||||
references.insert(*j.second);
|
||||
}
|
||||
attrs.alloc(state.sOutputs).mkList(outputsList);
|
||||
|
||||
// Copy the meta attributes.
|
||||
auto meta = state.buildBindings(metaNames.size());
|
||||
|
@ -98,11 +96,14 @@ bool createUserEnv(EvalState & state, PackageInfos & elems,
|
|||
|
||||
attrs.alloc(state.sMeta).mkAttrs(meta);
|
||||
|
||||
(manifest.listElems()[n++] = state.allocValue())->mkAttrs(attrs);
|
||||
(list[n] = state.allocValue())->mkAttrs(attrs);
|
||||
|
||||
if (drvPath) references.insert(*drvPath);
|
||||
}
|
||||
|
||||
Value manifest;
|
||||
manifest.mkList(list);
|
||||
|
||||
/* Also write a copy of the list of user environment elements to
|
||||
the store; we need it for future modifications of the
|
||||
environment. */
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue