Slightly more robust resource management

This commit is contained in:
2024-02-26 12:47:46 -06:00
parent 94a8bdca79
commit c35cea6213
3 changed files with 34 additions and 22 deletions

View File

@@ -1,10 +1,9 @@
#include "ljkiwi.hpp"
#include "ckiwi.h" #include "ckiwi.h"
#include <kiwi/kiwi.h> #include <kiwi/kiwi.h>
#include <cstdlib>
#include <climits> #include <climits>
#include <cstdlib>
#include <cstring> #include <cstring>
#include <string> #include <string>
@@ -38,15 +37,18 @@ const KiwiErr* new_error(const KiwiErr* base, const std::exception& ex) {
static const constexpr KiwiErr kKiwiErrUnhandledCxxException { static const constexpr KiwiErr kKiwiErrUnhandledCxxException {
KiwiErrUnknown, KiwiErrUnknown,
"An unhandled C++ exception occurred."}; "An unhandled C++ exception occurred."
};
static const constexpr KiwiErr kKiwiErrNullObjectArg0 { static const constexpr KiwiErr kKiwiErrNullObjectArg0 {
KiwiErrNullObject, KiwiErrNullObject,
"null object passed as argument #0 (self)"}; "null object passed as argument #0 (self)"
};
static const constexpr KiwiErr kKiwiErrNullObjectArg1 { static const constexpr KiwiErr kKiwiErrNullObjectArg1 {
KiwiErrNullObject, KiwiErrNullObject,
"null object passed as argument #1"}; "null object passed as argument #1"
};
template<typename F> template<typename F>
const KiwiErr* wrap_err(F&& f) { const KiwiErr* wrap_err(F&& f) {
@@ -55,42 +57,49 @@ const KiwiErr* wrap_err(F&& f) {
} catch (const UnsatisfiableConstraint& ex) { } catch (const UnsatisfiableConstraint& ex) {
static const constexpr KiwiErr err { static const constexpr KiwiErr err {
KiwiErrUnsatisfiableConstraint, KiwiErrUnsatisfiableConstraint,
"The constraint cannot be satisfied."}; "The constraint cannot be satisfied."
};
return &err; return &err;
} catch (const UnknownConstraint& ex) { } catch (const UnknownConstraint& ex) {
static const constexpr KiwiErr err { static const constexpr KiwiErr err {
KiwiErrUnknownConstraint, KiwiErrUnknownConstraint,
"The constraint has not been added to the solver."}; "The constraint has not been added to the solver."
};
return &err; return &err;
} catch (const DuplicateConstraint& ex) { } catch (const DuplicateConstraint& ex) {
static const constexpr KiwiErr err { static const constexpr KiwiErr err {
KiwiErrDuplicateConstraint, KiwiErrDuplicateConstraint,
"The constraint has already been added to the solver."}; "The constraint has already been added to the solver."
};
return &err; return &err;
} catch (const UnknownEditVariable& ex) { } catch (const UnknownEditVariable& ex) {
static const constexpr KiwiErr err { static const constexpr KiwiErr err {
KiwiErrUnknownEditVariable, KiwiErrUnknownEditVariable,
"The edit variable has not been added to the solver."}; "The edit variable has not been added to the solver."
};
return &err; return &err;
} catch (const DuplicateEditVariable& ex) { } catch (const DuplicateEditVariable& ex) {
static const constexpr KiwiErr err { static const constexpr KiwiErr err {
KiwiErrDuplicateEditVariable, KiwiErrDuplicateEditVariable,
"The edit variable has already been added to the solver."}; "The edit variable has already been added to the solver."
};
return &err; return &err;
} catch (const BadRequiredStrength& ex) { } catch (const BadRequiredStrength& ex) {
static const constexpr KiwiErr err { static const constexpr KiwiErr err {
KiwiErrBadRequiredStrength, KiwiErrBadRequiredStrength,
"A required strength cannot be used in this context."}; "A required strength cannot be used in this context."
};
return &err; return &err;
} catch (const InternalSolverError& ex) { } catch (const InternalSolverError& ex) {
static const constexpr KiwiErr base { static const constexpr KiwiErr base {
KiwiErrInternalSolverError, KiwiErrInternalSolverError,
"An internal solver error occurred."}; "An internal solver error occurred."
};
return new_error(&base, ex); return new_error(&base, ex);
} catch (std::bad_alloc&) { } catch (std::bad_alloc&) {
static const constexpr KiwiErr err {KiwiErrAlloc, "A memory allocation failed."}; static const constexpr KiwiErr err {KiwiErrAlloc, "A memory allocation failed."};
@@ -183,18 +192,19 @@ void kiwi_expression_retain(KiwiExpression* expr) {
for (auto* t = expr->terms_; t != expr->terms_ + expr->term_count; ++t) { for (auto* t = expr->terms_; t != expr->terms_ + expr->term_count; ++t) {
retain_unmanaged(t->var); retain_unmanaged(t->var);
} }
expr->owner = expr;
} }
void kiwi_expression_destroy(KiwiExpression* expr) { void kiwi_expression_destroy(KiwiExpression* expr) {
if (lk_unlikely(!expr)) if (lk_unlikely(!expr || !expr->owner))
return; return;
if (expr->owner) { if (expr->owner == expr) {
release_unmanaged(expr->owner);
} else {
for (auto* t = expr->terms_; t != expr->terms_ + expr->term_count; ++t) { for (auto* t = expr->terms_; t != expr->terms_ + expr->term_count; ++t) {
release_unmanaged(t->var); release_unmanaged(t->var);
} }
} else {
release_unmanaged(static_cast<ConstraintData*>(expr->owner));
} }
} }
@@ -209,7 +219,7 @@ KiwiConstraint* kiwi_constraint_construct(
} }
std::vector<Term> terms; std::vector<Term> terms;
terms.reserve(static_cast<std::size_t>( terms.reserve(static_cast<decltype(terms)::size_type>(
(lhs && lhs->term_count > 0 ? lhs->term_count : 0) (lhs && lhs->term_count > 0 ? lhs->term_count : 0)
+ (rhs && rhs->term_count > 0 ? rhs->term_count : 0) + (rhs && rhs->term_count > 0 ? rhs->term_count : 0)
)); ));

View File

@@ -56,7 +56,7 @@ typedef struct KiwiTerm {
typedef struct KiwiExpression { typedef struct KiwiExpression {
double constant; double constant;
int term_count; int term_count;
KiwiConstraint* owner; void* owner;
#if defined(LJKIWI_LUAJIT_DEF) #if defined(LJKIWI_LUAJIT_DEF)
KiwiTerm terms_[?]; KiwiTerm terms_[?];

View File

@@ -53,7 +53,7 @@ typedef struct KiwiTerm {
typedef struct KiwiExpression { typedef struct KiwiExpression {
double constant; double constant;
int term_count; int term_count;
KiwiConstraint* owner; void* owner;
KiwiTerm terms_[?]; KiwiTerm terms_[?];
} KiwiExpression; } KiwiExpression;
@@ -227,7 +227,7 @@ local function new_expr_one(constant, var, coeff)
dt.coefficient = coeff or 1.0 dt.coefficient = coeff or 1.0
ret.constant = constant ret.constant = constant
ret.term_count = 1 ret.term_count = 1
ljkiwi.kiwi_var_retain(var) ljkiwi.kiwi_expression_retain(ret)
return ret return ret
end end
@@ -500,9 +500,11 @@ do
end end
function Term_mt.__new(T, var, coefficient) function Term_mt.__new(T, var, coefficient)
local t = ffi_new(T, var, coefficient or 1.0) local t = ffi_gc(ffi_new(T), term_gc) --[[@as kiwi.Term]]
ljkiwi.kiwi_var_retain(var) ljkiwi.kiwi_var_retain(var)
return ffi_gc(t, term_gc) t.var = var
t.coefficient = coefficient or 1.0
return t
end end
function Term_mt.__mul(a, b) function Term_mt.__mul(a, b)