whiteout: kill worm_thread, eliminate race #504

pull/510/head
nick black 4 years ago committed by Nick Black
parent 9fa52fcdef
commit 80a1185529

@ -7,12 +7,6 @@
#include <pthread.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
// 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);

Loading…
Cancel
Save