stageobjects: add type-based macros for acquiring from/releasing into the correct pool

This commit is contained in:
Andrei Alexeyev 2024-06-05 21:58:58 +02:00
parent 13ace0e5c0
commit b81f338d2d
No known key found for this signature in database
GPG key ID: 72D26128040B9690
9 changed files with 71 additions and 54 deletions

View file

@ -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) {

View file

@ -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;
}

View file

@ -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) {

View file

@ -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;
}

View file

@ -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) {

View file

@ -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));

View file

@ -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);
}

View file

@ -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))

View file

@ -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;
}