whiteout: kill worm_thread, eliminate race #504

This commit is contained in:
nick black 2020-04-18 12:48:42 -04:00 committed by Nick Black
parent 9fa52fcdef
commit 80a1185529

View File

@ -7,12 +7,6 @@
#include <pthread.h> #include <pthread.h>
#include "demo.h" #include "demo.h"
// some random value to differentiate a demo abort, as indicated via
// demo_render() in worm_thread(). we can't use PTHREAD_CANCELED, since we
// do actually make use of cancellation.
static int demo_aborted = 0;
static void* DEMO_ABORTED = &demo_aborted;
// Fill up the screen with as much crazy Unicode as we can, and then set a // Fill up the screen with as much crazy Unicode as we can, and then set a
// gremlin loose, looking to brighten up the world. // gremlin loose, looking to brighten up the world.
@ -131,38 +125,42 @@ wormy(worm* s, int dimy, int dimx){
return 0; return 0;
} }
// each worm wanders around aimlessly. it lights up the cells around it; to do struct worm_ctx {
// this, we keep an array of 13 cells with the original colors, which we tune up. int wormcount;
static void * worm* worms;
worm_thread(void* vnc){ };
struct notcurses* nc = vnc;
int dimy, dimx; int init_worms(struct worm_ctx* wctx, int dimy, int dimx){
notcurses_term_dim_yx(nc, &dimy, &dimx); if((wctx->wormcount = (dimy * dimx) / 800) == 0){
int wormcount = (dimy * dimx) / 800; wctx->wormcount = 1;
worm worms[wormcount];
for(int s = 0 ; s < wormcount ; ++s){
init_worm(&worms[s], dimy, dimx);
} }
while(true){ if((wctx->worms = malloc(sizeof(*wctx->worms) * wctx->wormcount)) == NULL){
pthread_testcancel(); return -1;
for(int s = 0 ; s < wormcount ; ++s){ }
if(wormy_top(nc, &worms[s])){ for(int s = 0 ; s < wctx->wormcount ; ++s){
return NULL; init_worm(&wctx->worms[s], dimy, dimx);
} }
} return 0;
int err; }
if( (err = demo_render(nc)) ){
if(err > 0){ // the whiteworms wander around aimlessly, lighting up cells around themselves
return DEMO_ABORTED; static int
} worm_move(struct notcurses* nc, struct worm_ctx* wctx, int dimy, int dimx){
} for(int s = 0 ; s < wctx->wormcount ; ++s){
for(int s = 0 ; s < wormcount ; ++s){ if(wormy_top(nc, &wctx->worms[s])){
if(wormy(&worms[s], dimy, dimx)){ return -1;
return NULL;
}
} }
} }
return NULL; int err;
if( (err = demo_render(nc)) ){
return err;
}
for(int s = 0 ; s < wctx->wormcount ; ++s){
if(wormy(&wctx->worms[s], dimy, dimx)){
return -1;
}
}
return 0;
} }
static int static int
@ -555,27 +553,27 @@ int witherworm_demo(struct notcurses* nc){
} }
ncplane_fadein(n, &tv, demo_fader, NULL); ncplane_fadein(n, &tv, demo_fader, NULL);
} }
pthread_t tid;
// FIXME this could just be brought inline, no need for a thread struct worm_ctx wctx;
pthread_create(&tid, NULL, worm_thread, nc); if( (err = init_worms(&wctx, maxy, maxx)) ){
return err;
}
struct timespec cur;
do{ do{
struct timespec left, cur; if( (err = worm_move(nc, &wctx, maxy, maxx)) ){
clock_gettime(CLOCK_MONOTONIC, &cur);
timespec_subtract(&left, &screenend, &cur);
key = demo_getc(nc, &left, NULL);
clock_gettime(CLOCK_MONOTONIC, &cur);
int64_t ns = timespec_subtract_ns(&cur, &screenend);
if(ns > 0){
break; break;
} }
}while(key < 0); key = demo_getc_nblock(nc, NULL);
pthread_cancel(tid); clock_gettime(CLOCK_MONOTONIC, &cur);
void* result = NULL; if(timespec_to_ns(&screenend) < timespec_to_ns(&cur)){
pthread_join(tid, &result); break;
}
}while(key == 0);
ncplane_destroy(mess); ncplane_destroy(mess);
ncplane_destroy(math); ncplane_destroy(math);
if(result == DEMO_ABORTED){ if(err){
return 1; return err;
} }
if(key == NCKEY_RESIZE){ if(key == NCKEY_RESIZE){
DEMO_RENDER(nc); DEMO_RENDER(nc);