integrate task scheduling into the stage loop
This commit is contained in:
parent
5b0b676c0e
commit
76aef22e23
5 changed files with 69 additions and 53 deletions
|
@ -44,10 +44,6 @@ struct CoTask {
|
|||
uint32_t unique_id;
|
||||
};
|
||||
|
||||
struct CoSched {
|
||||
LIST_ANCHOR(CoTask) tasks, pending_tasks;
|
||||
};
|
||||
|
||||
static LIST_ANCHOR(CoTask) task_pool;
|
||||
static size_t num_tasks_allocated;
|
||||
static size_t num_tasks_in_use;
|
||||
|
@ -283,9 +279,8 @@ void coevent_cancel(CoEvent* evt) {
|
|||
evt->subscribers = NULL;
|
||||
}
|
||||
|
||||
CoSched *cosched_new(void) {
|
||||
CoSched *sched = calloc(1, sizeof(*sched));
|
||||
return sched;
|
||||
void cosched_init(CoSched *sched) {
|
||||
memset(sched, 0, sizeof(*sched));
|
||||
}
|
||||
|
||||
CoTask *cosched_new_task(CoSched *sched, CoTaskFunc func, void *arg) {
|
||||
|
@ -319,7 +314,7 @@ uint cosched_run_tasks(CoSched *sched) {
|
|||
return ran;
|
||||
}
|
||||
|
||||
void cosched_free(CoSched *sched) {
|
||||
void cosched_finish(CoSched *sched) {
|
||||
for(CoTask *t = sched->pending_tasks.first, *next; t; t = next) {
|
||||
next = t->next;
|
||||
cotask_free(t);
|
||||
|
@ -329,6 +324,8 @@ void cosched_free(CoSched *sched) {
|
|||
next = t->next;
|
||||
cotask_free(t);
|
||||
}
|
||||
|
||||
memset(sched, 0, sizeof(*sched));
|
||||
}
|
||||
|
||||
void coroutines_init(void) {
|
||||
|
|
|
@ -43,6 +43,10 @@ typedef struct CoEvent {
|
|||
uint8_t num_subscribers_allocated;
|
||||
} CoEvent;
|
||||
|
||||
struct CoSched {
|
||||
LIST_ANCHOR(CoTask) tasks, pending_tasks;
|
||||
};
|
||||
|
||||
void coroutines_init(void);
|
||||
void coroutines_shutdown(void);
|
||||
|
||||
|
@ -65,10 +69,10 @@ void coevent_signal(CoEvent *evt);
|
|||
void coevent_signal_once(CoEvent *evt);
|
||||
void coevent_cancel(CoEvent *evt);
|
||||
|
||||
CoSched *cosched_new(void);
|
||||
void cosched_init(CoSched *sched);
|
||||
CoTask *cosched_new_task(CoSched *sched, CoTaskFunc func, void *arg); // creates and runs the task, schedules it for resume on cosched_run_tasks if it's still alive
|
||||
uint cosched_run_tasks(CoSched *sched); // returns number of tasks ran
|
||||
void cosched_free(CoSched *sched);
|
||||
void cosched_finish(CoSched *sched);
|
||||
|
||||
static inline attr_must_inline void cosched_set_invoke_target(CoSched *sched) { _cosched_global = sched; }
|
||||
|
||||
|
|
68
src/stage.c
68
src/stage.c
|
@ -677,10 +677,11 @@ bool stage_is_cleared(void) {
|
|||
|
||||
typedef struct StageFrameState {
|
||||
StageInfo *stage;
|
||||
int transition_delay;
|
||||
uint16_t last_replay_fps;
|
||||
CallChain cc;
|
||||
CoSched sched;
|
||||
int transition_delay;
|
||||
int logic_calls;
|
||||
uint16_t last_replay_fps;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool skip_to_dialog;
|
||||
|
@ -728,6 +729,22 @@ static void stage_give_clear_bonus(const StageInfo *stage, StageClearBonus *bonu
|
|||
player_add_points(&global.plr, bonus->total, global.plr.pos);
|
||||
}
|
||||
|
||||
inline bool stage_should_yield(void) {
|
||||
return (global.boss && !boss_is_fleeing(global.boss)) || dialog_is_active(global.dialog);
|
||||
}
|
||||
|
||||
void stage_yield(void) {
|
||||
do {
|
||||
cotask_yield(NULL);
|
||||
} while(stage_should_yield());
|
||||
}
|
||||
|
||||
void stage_wait(int delay) {
|
||||
while(delay-- > 0) {
|
||||
stage_yield();
|
||||
}
|
||||
}
|
||||
|
||||
static LogicFrameAction stage_logic_frame(void *arg) {
|
||||
StageFrameState *fstate = arg;
|
||||
StageInfo *stage = fstate->stage;
|
||||
|
@ -757,7 +774,9 @@ static LogicFrameAction stage_logic_frame(void *arg) {
|
|||
((global.replaymode == REPLAY_PLAY) ? replay_input : stage_input)();
|
||||
|
||||
if(global.gameover != GAMEOVER_TRANSITIONING) {
|
||||
if((!global.boss || boss_is_fleeing(global.boss)) && !dialog_is_active(global.dialog)) {
|
||||
cosched_run_tasks(&fstate->sched);
|
||||
|
||||
if(!stage_should_yield()) {
|
||||
stage->procs->event();
|
||||
}
|
||||
|
||||
|
@ -839,16 +858,28 @@ static RenderFrameAction stage_render_frame(void *arg) {
|
|||
|
||||
static void stage_end_loop(void *ctx);
|
||||
|
||||
static void stage_stub_proc(void) { }
|
||||
|
||||
void stage_enter(StageInfo *stage, CallChain next) {
|
||||
assert(stage);
|
||||
assert(stage->procs);
|
||||
assert(stage->procs->preload);
|
||||
assert(stage->procs->begin);
|
||||
assert(stage->procs->end);
|
||||
assert(stage->procs->draw);
|
||||
assert(stage->procs->event);
|
||||
assert(stage->procs->update);
|
||||
assert(stage->procs->shader_rules);
|
||||
|
||||
#define STUB_PROC(proc, stub) do {\
|
||||
if(!stage->procs->proc) { \
|
||||
stage->procs->proc = stub; \
|
||||
log_debug(#proc " proc is missing"); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
static const ShaderRule shader_rules_stub[1] = { NULL };
|
||||
|
||||
STUB_PROC(preload, stage_stub_proc);
|
||||
STUB_PROC(begin, stage_stub_proc);
|
||||
STUB_PROC(end, stage_stub_proc);
|
||||
STUB_PROC(draw, stage_stub_proc);
|
||||
STUB_PROC(event, stage_stub_proc);
|
||||
STUB_PROC(update, stage_stub_proc);
|
||||
STUB_PROC(shader_rules, (ShaderRule*)shader_rules_stub);
|
||||
|
||||
if(global.gameover == GAMEOVER_WIN) {
|
||||
global.gameover = 0;
|
||||
|
@ -910,14 +941,9 @@ void stage_enter(StageInfo *stage, CallChain next) {
|
|||
stg->playpos = 0;
|
||||
}
|
||||
|
||||
stage->procs->begin();
|
||||
player_stage_post_init(&global.plr);
|
||||
|
||||
if(global.stage->type != STAGE_SPELL) {
|
||||
display_stage_title(stage);
|
||||
}
|
||||
|
||||
StageFrameState *fstate = calloc(1 , sizeof(*fstate));
|
||||
cosched_init(&fstate->sched);
|
||||
cosched_set_invoke_target(&fstate->sched);
|
||||
fstate->stage = stage;
|
||||
fstate->cc = next;
|
||||
|
||||
|
@ -925,6 +951,13 @@ void stage_enter(StageInfo *stage, CallChain next) {
|
|||
fstate->skip_to_dialog = env_get_int("TAISEI_SKIP_TO_DIALOG", 0);
|
||||
#endif
|
||||
|
||||
stage->procs->begin();
|
||||
player_stage_post_init(&global.plr);
|
||||
|
||||
if(global.stage->type != STAGE_SPELL) {
|
||||
display_stage_title(stage);
|
||||
}
|
||||
|
||||
eventloop_enter(fstate, stage_logic_frame, stage_render_frame, stage_end_loop, FPS);
|
||||
}
|
||||
|
||||
|
@ -944,6 +977,7 @@ void stage_end_loop(void* ctx) {
|
|||
stage_draw_shutdown();
|
||||
stage_free();
|
||||
player_free(&global.plr);
|
||||
cosched_finish(&s->sched);
|
||||
tsrand_switch(&global.rand_visual);
|
||||
free_all_refs();
|
||||
ent_shutdown();
|
||||
|
|
|
@ -149,6 +149,10 @@ bool stage_is_cleared(void);
|
|||
|
||||
void stage_unlock_bgm(const char *bgm);
|
||||
|
||||
bool stage_should_yield(void);
|
||||
void stage_yield(void);
|
||||
void stage_wait(int delay);
|
||||
|
||||
#include "stages/stage1.h"
|
||||
#include "stages/stage2.h"
|
||||
#include "stages/stage3.h"
|
||||
|
|
|
@ -13,10 +13,6 @@
|
|||
#include "global.h"
|
||||
#include "common_tasks.h"
|
||||
|
||||
static CoSched *cotest_sched;
|
||||
|
||||
static void cotest_stub_proc(void) { }
|
||||
|
||||
TASK(laserproj_death, { Projectile *p; }) {
|
||||
spawn_projectile_clear_effect(ARGS.p);
|
||||
}
|
||||
|
@ -144,40 +140,21 @@ TASK_FINALIZER(test_enemy) {
|
|||
TASK(stage_main, { int ignored; }) {
|
||||
YIELD;
|
||||
|
||||
WAIT(30);
|
||||
stage_wait(30);
|
||||
log_debug("test 1! %i", global.timer);
|
||||
WAIT(60);
|
||||
stage_wait(60);
|
||||
log_debug("test 2! %i", global.timer);
|
||||
|
||||
for(;;) {
|
||||
INVOKE_TASK_DELAYED(60, test_enemy, 9000, CMPLX(VIEWPORT_W, VIEWPORT_H) * 0.5, 3*I);
|
||||
WAIT(1000);
|
||||
stage_wait(1000);
|
||||
}
|
||||
}
|
||||
|
||||
static void cotest_begin(void) {
|
||||
cotest_sched = cosched_new();
|
||||
cosched_set_invoke_target(cotest_sched);
|
||||
INVOKE_TASK(stage_main, 0);
|
||||
}
|
||||
|
||||
static void cotest_end(void) {
|
||||
cosched_free(cotest_sched);
|
||||
}
|
||||
|
||||
static void cotest_events(void) {
|
||||
if(!global.gameover && !cosched_run_tasks(cotest_sched)) {
|
||||
log_debug("over!");
|
||||
stage_finish(GAMEOVER_SCORESCREEN);
|
||||
}
|
||||
}
|
||||
|
||||
StageProcs corotest_procs = {
|
||||
.begin = cotest_begin,
|
||||
.preload = cotest_stub_proc,
|
||||
.end = cotest_end,
|
||||
.draw = cotest_stub_proc,
|
||||
.update = cotest_stub_proc,
|
||||
.event = cotest_events,
|
||||
.shader_rules = (ShaderRule[]) { NULL },
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue