[ecs] Pass the registry in to the component destroy function

This makes it possible for hierarchies to clean themselves up (by
deleting their entities (though that will cause other problems later
when the hierarchy doesn't own the entities)), thus plugging a memory
leak when parsing passage text.
This commit is contained in:
Bill Currie 2024-01-02 16:48:22 +09:00
parent 35eec0b2e5
commit f5ebc1083f
11 changed files with 43 additions and 34 deletions

View file

@ -46,7 +46,7 @@ struct ecs_registry_s;
typedef struct component_s {
size_t size;
void (*create) (void *);
void (*destroy) (void *);
void (*destroy) (void *, struct ecs_registry_s *reg);
// comp is the registry component id (base + system component id)
uint32_t (*rangeid) (struct ecs_registry_s *reg, uint32_t ent,
uint32_t comp);
@ -78,7 +78,8 @@ COMPINLINE void *Component_CreateElements (const component_t *component,
uint32_t index, uint32_t count);
COMPINLINE void Component_DestroyElements (const component_t *component,
void *array,
uint32_t index, uint32_t count);
uint32_t index, uint32_t count,
struct ecs_registry_s *reg);
#undef COMPINLINE
#ifndef IMPLEMENT_ECS_COMPONENT_Funcs
@ -186,12 +187,13 @@ Component_CreateElements (const component_t *component, void *array,
COMPINLINE void
Component_DestroyElements (const component_t *component, void *array,
uint32_t index, uint32_t count)
uint32_t index, uint32_t count,
struct ecs_registry_s *reg)
{
if (component->destroy) {
for (uint32_t i = index; count-- > 0; i++) {
__auto_type dst = (byte *) array + i * component->size;
component->destroy (dst);
component->destroy (dst, reg);
}
}
}

View file

@ -88,7 +88,7 @@ void Hierarchy_RemoveHierarchy (hierarchy_t *hierarchy, uint32_t index,
hierref_t Hierarchy_SetParent (hierref_t dref, hierref_t sref,
struct ecs_registry_s *reg);
void Hierref_DestroyComponent (void *href);
void Hierref_DestroyComponent (void *href, struct ecs_registry_s *reg);
///@}

View file

@ -56,7 +56,7 @@ ecs_system_t effect_system;
static psystem_t *cl_tsystem;
static void
cl_destroy_trail (void *comp)
cl_destroy_trail (void *comp, ecs_registry_t *reg)
{
auto trail = *(uint32_t *) comp;
R_Trail_Destroy (cl_tsystem, trail);

View file

@ -35,7 +35,7 @@
#include "QF/ecs.h"
static void
ecs_name_destroy (void *name)
ecs_name_destroy (void *name, ecs_registry_t *reg)
{
free (name);
}
@ -47,7 +47,7 @@ ecs_hierarchy_create (void *hierarchy)
}
static void
ecs_hierarchy_destroy (void *hierarchy)
ecs_hierarchy_destroy (void *hierarchy, ecs_registry_t *reg)
{
Hierarchy_Destroy (hierarchy);
}
@ -87,7 +87,7 @@ ECS_DelRegistry (ecs_registry_t *registry)
for (uint32_t i = registry->components.size; i-- > 0 ;) {
__auto_type comp = &registry->components.a[i];
__auto_type pool = &registry->comp_pools[i];
Component_DestroyElements (comp, pool->data, 0, pool->count);
Component_DestroyElements (comp, pool->data, 0, pool->count, registry);
pool->count = 0;
}
free (registry->entities);
@ -268,7 +268,7 @@ ECS_RemoveEntities (ecs_registry_t *registry, uint32_t component)
if (destroy) {
byte *data = registry->comp_pools[component].data;
for (uint32_t i = 0; i < pool->count; i++) {
destroy (data + i * comp->size);
destroy (data + i * comp->size, registry);
}
}
pool->count = 0;

View file

@ -120,7 +120,7 @@ Ent_RemoveComponent (uint32_t ent, uint32_t comp, ecs_registry_t *registry)
// being double-removed due to deletion of the component resulting
// in the entity being deleted (happens with hierarchies)
pool->dense[ind] = -1;
Component_DestroyElements (c, pool->data, ind, 1);
Component_DestroyElements (c, pool->data, ind, 1, registry);
uint32_t range_count = subpool->num_ranges - subpool->available;
// if ind >= the last range, then it is outside the subpools
if (range_count && ind < subpool->ranges[range_count - 1]) {

View file

@ -474,8 +474,8 @@ Hierarchy_Create (hierarchy_t *hierarchy)
}
}
void
Hierarchy_Destroy (hierarchy_t *hierarchy)
static void
hierarchy_destroy (hierarchy_t *hierarchy)
{
free (hierarchy->ent);
free (hierarchy->childCount);
@ -491,6 +491,16 @@ Hierarchy_Destroy (hierarchy_t *hierarchy)
}
}
void
Hierarchy_Destroy (hierarchy_t *hierarchy)
{
hierarchy_InvalidateReferences (hierarchy, 0, hierarchy->num_objects);
for (uint32_t i = 0; i < hierarchy->num_objects; i++) {
ECS_DelEntity (hierarchy->reg, hierarchy->ent[i]);
}
hierarchy_destroy (hierarchy);
}
uint32_t
Hierarchy_New (ecs_registry_t *reg, uint32_t href_comp,
const hierarchy_type_t *type, bool createRoot)
@ -641,7 +651,7 @@ Hierarchy_SetTreeMode (hierarchy_t *hierarchy, bool tree_mode)
swap_pointers (&tmp.components[i], &src->components[i]);
}
}
Hierarchy_Destroy (&tmp);
hierarchy_destroy (&tmp);
}
uint32_t
@ -693,7 +703,6 @@ Hierarchy_SetParent (hierref_t dref, hierref_t sref, ecs_registry_t *reg)
if (src->tree_mode) {
Sys_Error ("Hierarchy_SetParent tree mode not implemented");
}
hierref_t r = {};
if (ECS_EntValid (dref.id, reg)) {
hierarchy_t *dst = Ent_GetComponent (dref.id, ecs_hierarchy, reg);
if (dst->type != src->type) {
@ -713,20 +722,19 @@ Hierarchy_SetParent (hierref_t dref, hierref_t sref, ecs_registry_t *reg)
if (!src->num_objects) {
Hierarchy_Delete (sref.id, reg);
}
return r;
return dref;
}
void
Hierref_DestroyComponent (void *href)
Hierref_DestroyComponent (void *href, ecs_registry_t *reg)
{
#if 0
hierref_t ref = *(hierref_t *) href;
if (ref.hierarchy) {
ref.hierarchy->ent[ref.index] = -1;
Hierarchy_RemoveHierarchy (ref.hierarchy, ref.index, 1);
if (!ref.hierarchy->num_objects) {
Hierarchy_Delete (ref.hierarchy);
if (ECS_EntValid (ref.id, reg)) {
hierarchy_t *h = Ent_GetComponent (ref.id, ecs_hierarchy, reg);
h->ent[ref.index] = -1;
Hierarchy_RemoveHierarchy (h, ref.index, 1);
if (!h->num_objects) {
Hierarchy_Delete (ref.id, reg);
}
}
#endif
}

View file

@ -68,7 +68,7 @@ create_colormap (void *_colormap)
}
static void
destroy_visibility (void *_visibility)
destroy_visibility (void *_visibility, ecs_registry_t *reg)
{
visibility_t *visibility = _visibility;
if (visibility->efrag) {
@ -77,7 +77,7 @@ destroy_visibility (void *_visibility)
}
static void
destroy_renderer (void *_renderer)
destroy_renderer (void *_renderer, ecs_registry_t *reg)
{
renderer_t *renderer = _renderer;
if (renderer->skin) {
@ -86,7 +86,7 @@ destroy_renderer (void *_renderer)
}
static void
destroy_efrags (void *_efrags)
destroy_efrags (void *_efrags, ecs_registry_t *reg)
{
efrag_t **efrags = _efrags;
R_ClearEfragChain (*efrags);

View file

@ -78,10 +78,9 @@ canvas_rangeid(outline)
#undef canvas_rangeid
static void
canvas_canvas_destroy (void *_canvas)
canvas_canvas_destroy (void *_canvas, ecs_registry_t *reg)
{
canvas_t *canvas = _canvas;
auto reg = canvas->reg;
for (uint32_t i = 0; i < canvas_subpool_count; i++) {
ECS_DelSubpoolRange (reg, canvas->base + i, canvas->range[i]);
}

View file

@ -129,7 +129,7 @@ struct imui_ctx_s {
};
static void
imui_reference_destroy (void *_ref)
imui_reference_destroy (void *_ref, ecs_registry_t *reg)
{
imui_reference_t *ref = _ref;
if (ref->ctx) {

View file

@ -45,7 +45,7 @@
#include "compat.h"
static void
text_passage_glyphs_destroy (void *_glyphset)
text_passage_glyphs_destroy (void *_glyphset, ecs_registry_t *reg)
{
glyphset_t *glyphset = _glyphset;
free (glyphset->glyphs);
@ -59,7 +59,7 @@ text_features_create (void *_features)
}
static void
text_features_destroy (void *_features)
text_features_destroy (void *_features, ecs_registry_t *reg)
{
featureset_t *features = _features;
DARRAY_CLEAR (features);

View file

@ -56,7 +56,7 @@ enum trails_components {
};
static void
destroy_pointset (void *comp)
pointset_destroy (void *comp, ecs_registry_t *reg)
{
pointset_t *pointset = comp;
int base = pointset->base / 64;
@ -71,7 +71,7 @@ static const component_t trails_components[trails_comp_count] = {
.size = sizeof (pointset_t),
.create = 0,
.name = "pointset",
.destroy = destroy_pointset,
.destroy = pointset_destroy,
},
};