93 lines
3.3 KiB
C
93 lines
3.3 KiB
C
|
#include "api.h"
|
||
|
|
||
|
#ifndef TASKMGR_MAX_TASKS
|
||
|
#define TASKMGR_MAX_TASKS 12
|
||
|
#endif
|
||
|
|
||
|
unsigned taskmgr_ms_till_next(void){
|
||
|
return 10;
|
||
|
}
|
||
|
|
||
|
static unsigned right_here=0;
|
||
|
|
||
|
struct run_tag {
|
||
|
int oneshot;/**<if true, free slot after first use (so setTimeout() rather than setInterval() basically)*/
|
||
|
int stack_up;/**<if true, run multiple times (max once per taskmgr_run() though) to catch up if we fall behind, else it is like dropframes*/
|
||
|
unsigned frequency_ms;
|
||
|
unsigned awaiting;/**<countdown*/
|
||
|
void(*cb)(void*ud);/**< this not being null means in use, if null, slot is free*/
|
||
|
void*ud;
|
||
|
char brief_descr[15+1];
|
||
|
unsigned deficit;/**<deposit left over change during stack_up logic*/
|
||
|
};
|
||
|
|
||
|
static unsigned time_passed(unsigned before,unsigned now){
|
||
|
unsigned timepassed=0;
|
||
|
if(now<before) {
|
||
|
timepassed = 0xfffffffful - before;
|
||
|
before=0;
|
||
|
}
|
||
|
timepassed += now-before;
|
||
|
return timepassed;
|
||
|
}
|
||
|
|
||
|
static struct run_tag run_tab[TASKMGR_MAX_TASKS];
|
||
|
/**@return true if there are stacked/immidiates left*/
|
||
|
static int one_loop(unsigned for_max_ms){
|
||
|
unsigned right_now = gettime_ms();
|
||
|
unsigned passed=0;
|
||
|
int i;
|
||
|
unsigned effective_passed;
|
||
|
int backed_up=0;
|
||
|
if(for_max_ms==0)for_max_ms=0xfffffffful;//0 means run at least once no matter what
|
||
|
/*--calc time passed--*/
|
||
|
if(right_now < right_here) {
|
||
|
/*--wrap around--*/
|
||
|
passed = right_now + (0xfffffffful - right_here);
|
||
|
} else passed = right_now - right_here;
|
||
|
/*--process all slots (active/inactive), some might be awaiting==0 so even if passed==0, still run--*/
|
||
|
for(i=0;i<TASKMGR_MAX_TASKS;++i){
|
||
|
if(run_tab[i].cb == NULL)continue;
|
||
|
effective_passed= passed + run_tab[i].deficit;
|
||
|
if(run_tab[i].awaiting < effective_passed) {
|
||
|
void(*task2run)(void*)=run_tab[i].cb;
|
||
|
void *taskParam = run_tab[i].ud;
|
||
|
effective_passed -= run_tab[i].awaiting;
|
||
|
if(effective_passed > 0 && effective_passed < run_tab[i].frequency_ms) {
|
||
|
run_tab[i].awaiting = run_tab[i].frequency_ms - effective_passed;
|
||
|
} else if(effective_passed > 0) {
|
||
|
backed_up=1;
|
||
|
if(run_tab[i].stack_up) {
|
||
|
/*--stack up logic--*/
|
||
|
run_tab[i].awaiting=0;
|
||
|
run_tab[i].deficit = effective_passed - run_tab[i].frequency_ms;
|
||
|
} else {
|
||
|
run_tab[i].awaiting=0;
|
||
|
}
|
||
|
}
|
||
|
if(run_tab[i].oneshot) {
|
||
|
run_tab[i].cb = NULL;
|
||
|
run_tab[i].ud = NULL;
|
||
|
}
|
||
|
task2run(run_tab[i].ud);
|
||
|
} else {
|
||
|
run_tab[i].awaiting -= effective_passed;
|
||
|
}
|
||
|
/*--deal with SLOW,LONG running callbacks vs for_max_ms "run for" issue--*/
|
||
|
if(time_passed(right_now,gettime_ms())>for_max_ms)break;
|
||
|
}
|
||
|
return backed_up;
|
||
|
}
|
||
|
void taskmgr_run(unsigned for_max_ms){
|
||
|
unsigned total_passed=0;
|
||
|
unsigned initial_moment = gettime_ms();
|
||
|
int backed_up = one_loop(for_max_ms);
|
||
|
if(for_max_ms > 0) {
|
||
|
while(backed_up) {
|
||
|
total_passed=time_passed(initial_moment,gettime_ms());
|
||
|
if(total_passed>=for_max_ms) break;
|
||
|
backed_up=one_loop(total_passed < for_max_ms ? for_max_ms - total_passed : 1);
|
||
|
}
|
||
|
}
|
||
|
}
|