mirror of
https://github.com/NixOS/nix
synced 2025-07-06 09:11:47 +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
|
@ -18,6 +18,7 @@
|
|||
|
||||
namespace nix {
|
||||
|
||||
struct Value;
|
||||
class BindingsBuilder;
|
||||
|
||||
|
||||
|
@ -134,6 +135,34 @@ class ExternalValueBase
|
|||
std::ostream & operator << (std::ostream & str, const ExternalValueBase & v);
|
||||
|
||||
|
||||
class ListBuilder
|
||||
{
|
||||
const size_t size;
|
||||
Value * inlineElems[2] = {nullptr, nullptr};
|
||||
public:
|
||||
Value * * elems;
|
||||
ListBuilder(EvalState & state, size_t size);
|
||||
|
||||
ListBuilder(ListBuilder && x)
|
||||
: size(x.size)
|
||||
, inlineElems{x.inlineElems[0], x.inlineElems[1]}
|
||||
, elems(size <= 2 ? inlineElems : x.elems)
|
||||
{ }
|
||||
|
||||
Value * & operator [](size_t n)
|
||||
{
|
||||
return elems[n];
|
||||
}
|
||||
|
||||
typedef Value * * iterator;
|
||||
|
||||
iterator begin() { return &elems[0]; }
|
||||
iterator end() { return &elems[size]; }
|
||||
|
||||
friend class Value;
|
||||
};
|
||||
|
||||
|
||||
struct Value
|
||||
{
|
||||
private:
|
||||
|
@ -323,16 +352,20 @@ public:
|
|||
|
||||
Value & mkAttrs(BindingsBuilder & bindings);
|
||||
|
||||
inline void mkList(size_t size)
|
||||
void mkList(const ListBuilder & builder)
|
||||
{
|
||||
clearValue();
|
||||
if (size == 1)
|
||||
if (builder.size == 1) {
|
||||
smallList[0] = builder.inlineElems[0];
|
||||
internalType = tList1;
|
||||
else if (size == 2)
|
||||
} else if (builder.size == 2) {
|
||||
smallList[0] = builder.inlineElems[0];
|
||||
smallList[1] = builder.inlineElems[1];
|
||||
internalType = tList2;
|
||||
else {
|
||||
} else {
|
||||
bigList.size = builder.size;
|
||||
bigList.elems = builder.elems;
|
||||
internalType = tListN;
|
||||
bigList.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue