mirror of
https://github.com/NixOS/nix
synced 2025-06-25 23:11:16 +02:00
refactor: Extract unsafe_new_with_self
This commit is contained in:
parent
1bd7517801
commit
f06f611ff3
1 changed files with 42 additions and 27 deletions
|
@ -19,6 +19,29 @@
|
||||||
# include <mutex>
|
# include <mutex>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allocate and initialize using self-reference
|
||||||
|
*
|
||||||
|
* This allows a brace initializer to reference the object being constructed.
|
||||||
|
*
|
||||||
|
* @warning Use with care, as the pointer points to an object that is not fully constructed yet.
|
||||||
|
*
|
||||||
|
* @tparam T Type to allocate
|
||||||
|
* @tparam F A function type for `init`, taking a T* and returning the initializer for T
|
||||||
|
* @param init Function that takes a T* and returns the initializer for T
|
||||||
|
* @return Pointer to allocated and initialized object
|
||||||
|
*/
|
||||||
|
template <typename T, typename F>
|
||||||
|
static T * unsafe_new_with_self(F && init)
|
||||||
|
{
|
||||||
|
// Allocate
|
||||||
|
void * p = ::operator new(
|
||||||
|
sizeof(T),
|
||||||
|
static_cast<std::align_val_t>(alignof(T)));
|
||||||
|
// Initialize with placement new
|
||||||
|
return new (p) T(init(static_cast<T *>(p)));
|
||||||
|
}
|
||||||
|
|
||||||
nix_err nix_libexpr_init(nix_c_context * context)
|
nix_err nix_libexpr_init(nix_c_context * context)
|
||||||
{
|
{
|
||||||
if (context)
|
if (context)
|
||||||
|
@ -99,18 +122,14 @@ nix_eval_state_builder * nix_eval_state_builder_new(nix_c_context * context, Sto
|
||||||
if (context)
|
if (context)
|
||||||
context->last_err_code = NIX_OK;
|
context->last_err_code = NIX_OK;
|
||||||
try {
|
try {
|
||||||
// Allocate ahead of time, because .settings needs self-reference
|
return unsafe_new_with_self<nix_eval_state_builder>([&](auto * self) {
|
||||||
void * p = ::operator new(
|
return nix_eval_state_builder{
|
||||||
sizeof(nix_eval_state_builder),
|
|
||||||
static_cast<std::align_val_t>(alignof(nix_eval_state_builder)));
|
|
||||||
auto * p2 = static_cast<nix_eval_state_builder *>(p);
|
|
||||||
new (p) nix_eval_state_builder{
|
|
||||||
.store = nix::ref<nix::Store>(store->ptr),
|
.store = nix::ref<nix::Store>(store->ptr),
|
||||||
.settings = nix::EvalSettings{/* &bool */ p2->readOnlyMode},
|
.settings = nix::EvalSettings{/* &bool */ self->readOnlyMode},
|
||||||
.fetchSettings = nix::fetchers::Settings{},
|
.fetchSettings = nix::fetchers::Settings{},
|
||||||
.readOnlyMode = true,
|
.readOnlyMode = true,
|
||||||
};
|
};
|
||||||
return p2;
|
});
|
||||||
}
|
}
|
||||||
NIXC_CATCH_ERRS_NULL
|
NIXC_CATCH_ERRS_NULL
|
||||||
}
|
}
|
||||||
|
@ -152,21 +171,17 @@ EvalState * nix_eval_state_build(nix_c_context * context, nix_eval_state_builder
|
||||||
if (context)
|
if (context)
|
||||||
context->last_err_code = NIX_OK;
|
context->last_err_code = NIX_OK;
|
||||||
try {
|
try {
|
||||||
// Allocate ahead of time, because .state init needs self-reference
|
return unsafe_new_with_self<EvalState>([&](auto * self) {
|
||||||
void * p = ::operator new(
|
return EvalState{
|
||||||
sizeof(EvalState),
|
|
||||||
static_cast<std::align_val_t>(alignof(EvalState)));
|
|
||||||
auto * p2 = static_cast<EvalState *>(p);
|
|
||||||
new (p) EvalState {
|
|
||||||
.fetchSettings = std::move(builder->fetchSettings),
|
.fetchSettings = std::move(builder->fetchSettings),
|
||||||
.settings = std::move(builder->settings),
|
.settings = std::move(builder->settings),
|
||||||
.state = nix::EvalState(
|
.state = nix::EvalState(
|
||||||
builder->lookupPath,
|
builder->lookupPath,
|
||||||
builder->store,
|
builder->store,
|
||||||
p2->fetchSettings,
|
self->fetchSettings,
|
||||||
p2->settings),
|
self->settings),
|
||||||
};
|
};
|
||||||
return p2;
|
});
|
||||||
}
|
}
|
||||||
NIXC_CATCH_ERRS_NULL
|
NIXC_CATCH_ERRS_NULL
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue