diff --git a/src/libexpr/nix_api_expr.cc b/src/libexpr/nix_api_expr.cc index 84d55ec13..880030380 100644 --- a/src/libexpr/nix_api_expr.cc +++ b/src/libexpr/nix_api_expr.cc @@ -110,33 +110,50 @@ std::unordered_map< std::mutex nix_refcount_lock; -void nix_gc_incref(const void *p) { - std::scoped_lock lock(nix_refcount_lock); - auto f = nix_refcounts.find(p); - if (f != nix_refcounts.end()) { - f->second++; - } else { - nix_refcounts[p] = 1; +nix_err nix_gc_incref(nix_c_context *context, const void *p) { + if (context) + context->last_err_code = NIX_OK; + try { + std::scoped_lock lock(nix_refcount_lock); + auto f = nix_refcounts.find(p); + if (f != nix_refcounts.end()) { + f->second++; + } else { + nix_refcounts[p] = 1; + } } + NIXC_CATCH_ERRS } -void nix_gc_decref(const void *p) { - std::scoped_lock lock(nix_refcount_lock); - auto f = nix_refcounts.find(p); - if (f != nix_refcounts.end()) { - if (f->second == 1) - nix_refcounts.erase(f); - else - f->second--; +nix_err nix_gc_decref(nix_c_context *context, const void *p) { + + if (context) + context->last_err_code = NIX_OK; + try { + std::scoped_lock lock(nix_refcount_lock); + auto f = nix_refcounts.find(p); + if (f != nix_refcounts.end()) { + if (--f->second == 0) + nix_refcounts.erase(f); + } else + throw std::runtime_error("nix_gc_decref: object was not referenced"); } - // todo: else { throw? } + NIXC_CATCH_ERRS } void nix_gc_now() { GC_gcollect(); } #else -void nix_gc_incref(const void *) {} -void nix_gc_decref(const void *) {} +void nix_gc_incref(nix_c_context *context, const void *) { + if (context) + context->last_err_code = NIX_OK; + return NIX_OK; +} +void nix_gc_decref(nix_c_context *context, const void *) { + if (context) + context->last_err_code = NIX_OK; + return NIX_OK; +} void nix_gc_now() {} #endif diff --git a/src/libexpr/nix_api_expr.h b/src/libexpr/nix_api_expr.h index 9efb3dde1..c56ef89bb 100644 --- a/src/libexpr/nix_api_expr.h +++ b/src/libexpr/nix_api_expr.h @@ -120,13 +120,13 @@ void nix_state_free(State *state); * * @param[in] object The object to keep alive */ -void nix_gc_incref(const void *); +nix_err nix_gc_incref(nix_c_context *, const void *); /** * @brief Decrease the GC refcount * * @param[in] object The object to stop referencing */ -void nix_gc_decref(const void *); +nix_err nix_gc_decref(nix_c_context *, const void *); /** * @brief Trigger the garbage collector manually diff --git a/src/libexpr/nix_api_external.cc b/src/libexpr/nix_api_external.cc index d72adee80..a927a4037 100644 --- a/src/libexpr/nix_api_external.cc +++ b/src/libexpr/nix_api_external.cc @@ -178,7 +178,7 @@ ExternalValue *nix_create_external_value(nix_c_context *context, (GC) #endif NixCExternalValue(*desc, v); - nix_gc_incref(ret); + nix_gc_incref(nullptr, ret); return (ExternalValue *)ret; } NIXC_CATCH_ERRS_NULL diff --git a/src/libexpr/nix_api_value.cc b/src/libexpr/nix_api_value.cc index f34907ef1..6e02b3310 100644 --- a/src/libexpr/nix_api_value.cc +++ b/src/libexpr/nix_api_value.cc @@ -49,7 +49,7 @@ PrimOp *nix_alloc_primop(nix_c_context *context, PrimOpFun fun, int arity, if (args) for (size_t i = 0; args[i]; i++) p->args.emplace_back(*args); - nix_gc_incref(p); + nix_gc_incref(nullptr, p); return (PrimOp *)p; } NIXC_CATCH_ERRS_NULL @@ -60,7 +60,7 @@ Value *nix_alloc_value(nix_c_context *context, State *state) { context->last_err_code = NIX_OK; try { Value *res = state->state.allocValue(); - nix_gc_incref(res); + nix_gc_incref(nullptr, res); return res; } NIXC_CATCH_ERRS_NULL @@ -208,7 +208,7 @@ Value *nix_get_list_byidx(nix_c_context *context, const Value *value, auto &v = check_value_not_null(value); assert(v.type() == nix::nList); auto *p = v.listElems()[ix]; - nix_gc_incref(p); + nix_gc_incref(nullptr, p); return (Value *)p; } NIXC_CATCH_ERRS_NULL @@ -224,7 +224,7 @@ Value *nix_get_attr_byname(nix_c_context *context, const Value *value, nix::Symbol s = state->state.symbols.create(name); auto attr = v.attrs->get(s); if (attr) { - nix_gc_incref(attr->value); + nix_gc_incref(nullptr, attr->value); return attr->value; } nix_set_err_msg(context, NIX_ERR_KEY, "missing attribute"); @@ -257,7 +257,7 @@ Value *nix_get_attr_byidx(nix_c_context *context, const Value *value, auto &v = check_value_not_null(value); const nix::Attr &a = (*v.attrs)[i]; *name = ((const std::string &)(state->state.symbols[a.name])).c_str(); - nix_gc_incref(a.value); + nix_gc_incref(nullptr, a.value); return a.value; } NIXC_CATCH_ERRS_NULL