From 80a1185529926ee6db2e4e1f783c5636b7da2708 Mon Sep 17 00:00:00 2001 From: nick black Date: Sat, 18 Apr 2020 12:48:42 -0400 Subject: [PATCH] whiteout: kill worm_thread, eliminate race #504 --- src/demo/whiteout.c | 96 ++++++++++++++++++++++----------------------- 1 file changed, 47 insertions(+), 49 deletions(-) diff --git a/src/demo/whiteout.c b/src/demo/whiteout.c index b0bd247f5..d8cb22f03 100644 --- a/src/demo/whiteout.c +++ b/src/demo/whiteout.c @@ -7,12 +7,6 @@ #include #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 // gremlin loose, looking to brighten up the world. @@ -131,38 +125,42 @@ wormy(worm* s, int dimy, int dimx){ return 0; } -// each worm wanders around aimlessly. it lights up the cells around it; to do -// this, we keep an array of 13 cells with the original colors, which we tune up. -static void * -worm_thread(void* vnc){ - struct notcurses* nc = vnc; - int dimy, dimx; - notcurses_term_dim_yx(nc, &dimy, &dimx); - int wormcount = (dimy * dimx) / 800; - worm worms[wormcount]; - for(int s = 0 ; s < wormcount ; ++s){ - init_worm(&worms[s], dimy, dimx); +struct worm_ctx { + int wormcount; + worm* worms; +}; + +int init_worms(struct worm_ctx* wctx, int dimy, int dimx){ + if((wctx->wormcount = (dimy * dimx) / 800) == 0){ + wctx->wormcount = 1; } - while(true){ - pthread_testcancel(); - for(int s = 0 ; s < wormcount ; ++s){ - if(wormy_top(nc, &worms[s])){ - return NULL; - } - } - int err; - if( (err = demo_render(nc)) ){ - if(err > 0){ - return DEMO_ABORTED; - } + if((wctx->worms = malloc(sizeof(*wctx->worms) * wctx->wormcount)) == NULL){ + return -1; + } + for(int s = 0 ; s < wctx->wormcount ; ++s){ + init_worm(&wctx->worms[s], dimy, dimx); + } + return 0; +} + +// the whiteworms wander around aimlessly, lighting up cells around themselves +static int +worm_move(struct notcurses* nc, struct worm_ctx* wctx, int dimy, int dimx){ + for(int s = 0 ; s < wctx->wormcount ; ++s){ + if(wormy_top(nc, &wctx->worms[s])){ + return -1; } - for(int s = 0 ; s < wormcount ; ++s){ - if(wormy(&worms[s], dimy, dimx)){ - 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 NULL; + return 0; } static int @@ -555,27 +553,27 @@ int witherworm_demo(struct notcurses* nc){ } ncplane_fadein(n, &tv, demo_fader, NULL); } - pthread_t tid; - // FIXME this could just be brought inline, no need for a thread - pthread_create(&tid, NULL, worm_thread, nc); + + struct worm_ctx wctx; + if( (err = init_worms(&wctx, maxy, maxx)) ){ + return err; + } + struct timespec cur; do{ - struct timespec left, cur; - clock_gettime(CLOCK_MONOTONIC, &cur); - timespec_subtract(&left, &screenend, &cur); - key = demo_getc(nc, &left, NULL); + if( (err = worm_move(nc, &wctx, maxy, maxx)) ){ + break; + } + key = demo_getc_nblock(nc, NULL); clock_gettime(CLOCK_MONOTONIC, &cur); - int64_t ns = timespec_subtract_ns(&cur, &screenend); - if(ns > 0){ + if(timespec_to_ns(&screenend) < timespec_to_ns(&cur)){ break; } - }while(key < 0); - pthread_cancel(tid); - void* result = NULL; - pthread_join(tid, &result); + }while(key == 0); + ncplane_destroy(mess); ncplane_destroy(math); - if(result == DEMO_ABORTED){ - return 1; + if(err){ + return err; } if(key == NCKEY_RESIZE){ DEMO_RENDER(nc);