From b81f338d2d96c2779fc7b4c6c44854168fa39583 Mon Sep 17 00:00:00 2001 From: Andrei Alexeyev Date: Wed, 5 Jun 2024 21:58:58 +0200 Subject: [PATCH] stageobjects: add type-based macros for acquiring from/releasing into the correct pool --- src/boss.c | 4 ++-- src/enemy.c | 4 ++-- src/item.c | 6 ++--- src/lasers/laser.c | 6 ++--- src/projectile.c | 4 ++-- src/stagedraw.c | 10 ++++---- src/stageobjects.c | 22 +++++++----------- src/stageobjects.h | 58 +++++++++++++++++++++++++++++++++------------- src/stagetext.c | 11 ++++----- 9 files changed, 71 insertions(+), 54 deletions(-) diff --git a/src/boss.c b/src/boss.c index ac645c8a..958c4863 100644 --- a/src/boss.c +++ b/src/boss.c @@ -54,7 +54,7 @@ TASK(boss_damage_to_power, { BoxedBoss boss; }) { } Boss *create_boss(const char *name, char *ani, cmplx pos) { - Boss *boss = mempool_acquire(&stage_object_pools.bosses); + auto boss = STAGE_ACQUIRE_OBJ(Boss); boss->name = name; boss->pos = pos; @@ -1364,7 +1364,7 @@ void free_boss(Boss *boss) { ent_unregister(&boss->ent); boss_set_portrait(boss, NULL, NULL, NULL); aniplayer_free(&boss->ani); - mempool_release(&stage_object_pools.bosses, boss); + STAGE_RELEASE_OBJ(boss); } static void boss_schedule_next_attack(Boss *b, Attack *a) { diff --git a/src/enemy.c b/src/enemy.c index 13763335..1c99a62f 100644 --- a/src/enemy.c +++ b/src/enemy.c @@ -87,7 +87,7 @@ Enemy *create_enemy_p(EnemyList *enemies, cmplx pos, float hp, EnemyVisual visua log_fatal("Tried to spawn an enemy while in drawing code"); } - Enemy *e = alist_append(enemies, (Enemy*)mempool_acquire(&stage_object_pools.enemies)); + auto e = alist_append(enemies, STAGE_ACQUIRE_OBJ(Enemy)); e->moving = false; e->dir = 0; e->birthtime = global.frames; @@ -165,7 +165,7 @@ static void *_delete_enemy(ListAnchor *enemies, List* enemy, void *arg) { COEVENT_CANCEL_ARRAY(e->events); ent_unregister(&e->ent); - mempool_release(&stage_object_pools.enemies, alist_unlink(enemies, e)); + STAGE_RELEASE_OBJ(alist_unlink(enemies, e)); return NULL; } diff --git a/src/item.c b/src/item.c index 05caeb46..526b135f 100644 --- a/src/item.c +++ b/src/item.c @@ -130,9 +130,7 @@ Item *create_item(cmplx pos, cmplx v, ItemType type) { type = ITEM_SURGE; } - Item *i = mempool_acquire(&stage_object_pools.items); - alist_append(&global.items, i); - + auto i = alist_append(&global.items, STAGE_ACQUIRE_OBJ(Item)); i->pos = pos; i->pos0 = pos; i->v = v; @@ -150,7 +148,7 @@ Item *create_item(cmplx pos, cmplx v, ItemType type) { void delete_item(Item *item) { ent_unregister(&item->ent); - mempool_release(&stage_object_pools.items, alist_unlink(&global.items, item)); + STAGE_RELEASE_OBJ(alist_unlink(&global.items, item)); } Item *create_clear_item(cmplx pos, uint clear_flags) { diff --git a/src/lasers/laser.c b/src/lasers/laser.c index 323f8c92..014fe932 100644 --- a/src/lasers/laser.c +++ b/src/lasers/laser.c @@ -55,9 +55,7 @@ void lasers_shutdown(void) { } Laser *create_laser(cmplx pos, float time, float deathtime, const Color *color, LaserRule rule) { - Laser *l = mempool_acquire(&stage_object_pools.lasers); - alist_push(&global.lasers, l); - + auto l = alist_push(&global.lasers, STAGE_ACQUIRE_OBJ(Laser)); l->birthtime = global.frames; l->timespan = time; l->deathtime = deathtime; @@ -113,7 +111,7 @@ void laserline_set_posdir(Laser *l, cmplx pos, cmplx dir) { static void *_delete_laser(ListAnchor *lasers, List *laser, void *arg) { Laser *l = (Laser*)laser; ent_unregister(&l->ent); - mempool_release(&stage_object_pools.lasers, alist_unlink(lasers, l)); + STAGE_RELEASE_OBJ(alist_unlink(lasers, l)); return NULL; } diff --git a/src/projectile.c b/src/projectile.c index 362f00ff..7208df29 100644 --- a/src/projectile.c +++ b/src/projectile.c @@ -245,7 +245,7 @@ static Projectile* _create_projectile(ProjArgs *args) { log_fatal("Tried to spawn a projectile while in drawing code"); } - Projectile *p = mempool_acquire(&stage_object_pools.projectiles); + auto p = STAGE_ACQUIRE_OBJ(Projectile); p->birthtime = global.frames; p->pos = p->pos0 = p->prevpos = args->pos; @@ -326,7 +326,7 @@ static void delete_projectile(ProjectileList *projlist, Projectile *p, ProjColli signal_event_with_collision_result(p, &p->events.killed, col); COEVENT_CANCEL_ARRAY(p->events); ent_unregister(&p->ent); - mempool_release(&stage_object_pools.projectiles, alist_unlink(projlist, p)); + STAGE_RELEASE_OBJ(alist_unlink(projlist, p)); } static void *foreach_delete_projectile(ListAnchor *projlist, List *proj, void *arg) { diff --git a/src/stagedraw.c b/src/stagedraw.c index 31e1fa68..15d51b07 100644 --- a/src/stagedraw.c +++ b/src/stagedraw.c @@ -1167,8 +1167,8 @@ static void stage_draw_hud_scores(float ypos_hiscore, float ypos_score, char *bu static void stage_draw_hud_objpool_stats(float x, float y, float width) { char buf[128]; - auto objpools = STAGE_OBJPOOLS_AS_ARRAYPTR; - MemArena *arena = (*objpools)[0].arena; + auto objpools = &stage_objects.pools.as_array; + MemArena *arena = &stage_objects.arena; Font *font = res_font("monotiny"); @@ -1198,9 +1198,9 @@ static void stage_draw_hud_objpool_stats(float x, float y, float width) { y += lineskip * 1.5; const char *const names[] = { - #define OBJECT_POOL(t, n) #t, - OBJECT_POOLS - #undef OBJECT_POOL + #define GET_POOL_NAME(t, n) #t, + OBJECT_POOLS(GET_POOL_NAME) + #undef GET_POOL_NAME }; static_assert(ARRAY_SIZE(*objpools) == ARRAY_SIZE(names)); diff --git a/src/stageobjects.c b/src/stageobjects.c index aa16e8ea..74c31113 100644 --- a/src/stageobjects.c +++ b/src/stageobjects.c @@ -10,26 +10,22 @@ #define INIT_ARENA_SIZE (8 << 20) -StageObjectPools stage_object_pools; - -static struct { - MemArena arena; -} stgobjs; +StageObjects stage_objects; void stage_objpools_init(void) { - if(!stgobjs.arena.pages.first) { - marena_init(&stgobjs.arena, INIT_ARENA_SIZE - sizeof(MemArenaPage)); + if(!stage_objects.arena.pages.first) { + marena_init(&stage_objects.arena, INIT_ARENA_SIZE - sizeof(MemArenaPage)); } else { - marena_reset(&stgobjs.arena); + marena_reset(&stage_objects.arena); } - #define OBJECT_POOL(type, field) \ - mempool_init(&stage_object_pools.field, &stgobjs.arena); + #define INIT_POOL(type, field) \ + mempool_init(&stage_objects.pools.field, &stage_objects.arena); - OBJECT_POOLS - #undef OBJECT_POOL + OBJECT_POOLS(INIT_POOL) + #undef INIT_POOL } void stage_objpools_shutdown(void) { - marena_deinit(&stgobjs.arena); + marena_deinit(&stage_objects.arena); } diff --git a/src/stageobjects.h b/src/stageobjects.h index 49ec2b03..a852d655 100644 --- a/src/stageobjects.h +++ b/src/stageobjects.h @@ -18,29 +18,55 @@ #include "stagetext.h" // IWYU pragma: export #include "boss.h" // IWYU pragma: export -#define OBJECT_POOLS \ - OBJECT_POOL(Projectile, projectiles) \ - OBJECT_POOL(Item, items) \ - OBJECT_POOL(Enemy, enemies) \ - OBJECT_POOL(Laser, lasers) \ - OBJECT_POOL(StageText, stagetext) \ - OBJECT_POOL(Boss, bosses) \ +#define OBJECT_POOLS(X) \ + X(Projectile, projectiles) \ + X(Item, items) \ + X(Enemy, enemies) \ + X(Laser, lasers) \ + X(StageText, stagetext) \ + X(Boss, bosses) \ -typedef struct StageObjectPools { - #define OBJECT_POOL(type, field) \ - MEMPOOL(type) field; +enum { + #define COUNT_POOL(...) 1 + + NUM_STAGE_OBJECT_POOLS = OBJECT_POOLS(COUNT_POOL) 0, + #undef COUNT_POOL +}; - OBJECT_POOLS - #undef OBJECT_POOL -} StageObjectPools; +typedef struct StageObjects { + MemArena arena; + union { + struct { + #define DECLARE_POOL(type, field) \ + MEMPOOL(type) field; -extern StageObjectPools stage_object_pools; + OBJECT_POOLS(DECLARE_POOL) + #undef DECLARE_POOL + }; + MemPool as_array[NUM_STAGE_OBJECT_POOLS]; + } pools; +} StageObjects; -#define STAGE_OBJPOOLS_AS_ARRAYPTR \ - (MemPool (*)[sizeof(stage_object_pools) / sizeof(MemPool)])&stage_object_pools +extern StageObjects stage_objects; + +#define STAGE_OBJPOOL_GENERIC_DISPATCH(_type, _field) \ + _type*: &stage_objects.pools._field, + +#define STAGE_OBJPOOL_BY_VARTYPE(_p_obj) \ + _Generic((_p_obj), \ + OBJECT_POOLS(STAGE_OBJPOOL_GENERIC_DISPATCH) \ + struct {}: abort()) + +#define STAGE_OBJPOOL_BY_TYPE(type) \ + STAGE_OBJPOOL_BY_VARTYPE(&(type) {}) // Can be called many times to reinitialize the pools while reusing allocated arena memory. void stage_objpools_init(void); // Frees the arena void stage_objpools_shutdown(void); + +#define STAGE_ACQUIRE_OBJ(_type) \ + mempool_acquire(STAGE_OBJPOOL_BY_TYPE(_type)) + +#define STAGE_RELEASE_OBJ(_p_obj) \ + mempool_release(STAGE_OBJPOOL_BY_VARTYPE(_p_obj), (_p_obj)) diff --git a/src/stagetext.c b/src/stagetext.c index 2a8b1302..c5446e16 100644 --- a/src/stagetext.c +++ b/src/stagetext.c @@ -13,9 +13,8 @@ static StageText *textlist = NULL; -StageText* stagetext_add(const char *text, cmplx pos, Alignment align, Font *font, const Color *clr, int delay, int lifetime, int fadeintime, int fadeouttime) { - StageText *t = mempool_acquire(&stage_object_pools.stagetext); - list_append(&textlist, t); +StageText *stagetext_add(const char *text, cmplx pos, Alignment align, Font *font, const Color *clr, int delay, int lifetime, int fadeintime, int fadeouttime) { + auto t = list_append(&textlist, STAGE_ACQUIRE_OBJ(StageText)); if(text != NULL) { assert(strlen(text) < sizeof(t->text)); @@ -39,15 +38,15 @@ static void stagetext_numeric_update(StageText *txt, int t, float a) { format_huge_num(0, (uintptr_t)txt->custom.data1 * pow(a, 5), sizeof(txt->text), txt->text); } -StageText* stagetext_add_numeric(int n, cmplx pos, Alignment align, Font *font, const Color *clr, int delay, int lifetime, int fadeintime, int fadeouttime) { - StageText *t = stagetext_add(NULL, pos, align, font, clr, delay, lifetime, fadeintime, fadeouttime); +StageText *stagetext_add_numeric(int n, cmplx pos, Alignment align, Font *font, const Color *clr, int delay, int lifetime, int fadeintime, int fadeouttime) { + auto t = stagetext_add(NULL, pos, align, font, clr, delay, lifetime, fadeintime, fadeouttime); t->custom.data1 = (void*)(intptr_t)n; t->custom.update = stagetext_numeric_update; return t; } static void *stagetext_delete(List **dest, List *txt, void *arg) { - mempool_release(&stage_object_pools.stagetext, list_unlink(dest, (StageText*)txt)); + STAGE_RELEASE_OBJ(list_unlink(dest, (StageText*)txt)); return NULL; }