shithub: battleship

Download patch

ref: e29fc9d0f23c62085114cb479032e07b0fb29abb
parent: 2723bb6ff3e339f7f56a6276fa1c7c9f28d63871
author: Amavect <[email protected]>
date: Wed Sep 6 22:38:36 EDT 2023

inline spawned threads to threadmain.

Pointers to automatic variables become invalid
when threadmain exits.
Solution is to reuse threadmain.
Use nbsend to avoid deadlock to the draw channel.
Input struct is no longer needed, inline it.

--- a/bts.c
+++ b/bts.c
@@ -344,7 +344,7 @@
 		}
 	}
 
-	send(drawchan, nil);
+	nbsend(drawchan, nil);
 }
 
 void
@@ -500,7 +500,7 @@
 		}
 		break;
 	}
-	send(drawchan, nil);
+	nbsend(drawchan, nil);
 }
 
 void
@@ -536,7 +536,7 @@
 		if(rectXarmada(curship->bbox))
 			curship->bbox = ZR;
 
-		send(drawchan, nil);
+		nbsend(drawchan, nil);
 	}
 }
 
@@ -584,7 +584,7 @@
 		layoutdone++;
 		break;
 	}
-	send(drawchan, nil);
+	nbsend(drawchan, nil);
 }
 
 void
@@ -605,7 +605,7 @@
 		if(rectinrect(newbbox, localboard.bbox) && !rectXarmada(newbbox)){
 			curship->p = toboard(&localboard, mc->xy);
 			curship->bbox = newbbox;
-			send(drawchan, nil);
+			nbsend(drawchan, nil);
 		}
 	}
 
@@ -639,44 +639,6 @@
 }
 
 void
-bobross(void *)
-{
-	while(recv(drawchan, nil) > 0)
-		redraw();
-	sysfatal("painter died");
-}
-
-void
-inputthread(void *arg)
-{
-	Input *in;
-	Rune r;
-	Alt a[4];
-
-	in = arg;
-
-	a[0].c = in->mc->c; a[0].v = &in->mc->Mouse; a[0].op = CHANRCV;
-	a[1].c = in->mc->resizec; a[1].v = nil; a[1].op = CHANRCV;
-	a[2].c = in->kc->c; a[2].v = &r; a[2].op = CHANRCV;
-	a[3].op = CHANEND;
-
-	for(;;)
-		switch(alt(a)){
-		case -1:
-			sysfatal("input thread interrupted");
-		case 0:
-			mouse(in->mc);
-			break;
-		case 1:
-			resize();
-			break;
-		case 2:
-			key(r);
-			break;
-		}
-}
-
-void
 celebrate(void)
 {
 	static Image *c;
@@ -762,7 +724,7 @@
 		}
 		break;
 	}
-	send(drawchan, nil);
+	nbsend(drawchan, nil);
 }
 
 void
@@ -821,15 +783,10 @@
 threadmain(int argc, char *argv[])
 {
 	char *addr;
-	/*
-	 * TODO
-	 * if it's not static it messes with in.mc->xy later, probably
-	 * because of an stack overflow somewhere.  have to investigate
-	 * with wpset("w", &in.mc->xy, sizeof(Point*)); in acid(1)
-	 */
-	static char *user;
+	char *user;
 	int fd;
-	Input in;
+	Mousectl *mc;
+	Keyboardctl *kc;
 
 	GEOMfmtinstall();
 	ARGBEGIN{
@@ -856,15 +813,15 @@
 		sysfatal("newwindow: %r");
 	if(initdraw(nil, deffont, "bts") < 0)
 		sysfatal("initdraw: %r");
-	if((in.mc = initmouse(nil, screen)) == nil)
+	if((mc = initmouse(nil, screen)) == nil)
 		sysfatal("initmouse: %r");
-	if((in.kc = initkeyboard(nil)) == nil)
+	if((kc = initkeyboard(nil)) == nil)
 		sysfatal("initkeyboard: %r");
 
 	display->locking = 1;
 	unlockdisplay(display);
 
-	mctl = in.mc;
+	mctl = mc;
 	if((user = getenv("user")) == nil)
 		user = getuser();
 	snprint(uid, sizeof uid, "%s", user);
@@ -880,13 +837,38 @@
 	game.state = Waiting0;
 	csetcursor(mctl, &patrolcursor);
 
-	drawchan = chancreate(sizeof(void*), 0);
+	drawchan = chancreate(sizeof(void*), 1);
 	ingress = chancreate(sizeof(char*), 1);
 	egress = chancreate(sizeof(char*), 1);
-	threadcreate(bobross, nil, mainstacksize);
-	threadcreate(inputthread, &in, mainstacksize);
 	threadcreate(netrecvthread, &fd, mainstacksize);
 	threadcreate(netsendthread, &fd, mainstacksize);
-	send(drawchan, nil);
-	yield();
+	nbsend(drawchan, nil);
+
+	Rune r;
+	enum {MOUSE, RESIZE, KEYS, DRAW, NONE};
+	Alt a[] = {
+	[MOUSE]  = {mc->c, &mc->Mouse, CHANRCV},
+	[RESIZE] = {mc->resizec, nil, CHANRCV},
+	[KEYS]   = {kc->c, &r, CHANRCV},
+	[DRAW]   = {drawchan, nil, CHANRCV},
+	[NONE]   = {nil, nil, CHANEND}
+	};
+
+	for(;;)
+		switch(alt(a)){
+		default:
+			sysfatal("input thread interrupted");
+		case MOUSE:
+			mouse(mc);
+			break;
+		case RESIZE:
+			resize();
+			break;
+		case KEYS:
+			key(r);
+			break;
+		case DRAW:
+			redraw();
+			break;
+		}
 }
--- a/btsd.c
+++ b/btsd.c
@@ -299,14 +299,12 @@
 }
 
 void
-listenthread(void *arg)
+listenthread(char *addr)
 {
-	char *addr, adir[40], ldir[40], aux[128], *s;
+	char adir[40], ldir[40], aux[128], *s;
 	int acfd, lcfd, dfd, sfd;
 	Player *p;
 
-	addr = arg;
-
 	acfd = announce(addr, adir);
 	if(acfd < 0)
 		sysfatal("announce: %r");
@@ -357,6 +355,7 @@
 	case 'a':
 		addr = EARGF(usage());
 		break;
+	default: usage();
 	}ARGEND
 	if(argc != 0)
 		usage();
@@ -363,6 +362,5 @@
 
 	proccreate(matchmaker, nil, mainstacksize);
 	proccreate(reaper, nil, mainstacksize);
-	threadcreate(listenthread, addr, mainstacksize);
-	yield();
+	listenthread(addr);
 }
--- a/dat.h
+++ b/dat.h
@@ -31,7 +31,6 @@
 	KB = 1024,
 };
 
-typedef struct Input Input;
 typedef struct Ship Ship;
 typedef struct Map Map;
 typedef struct Board Board;
@@ -39,12 +38,6 @@
 typedef struct Playerq Playerq;
 typedef struct Match Match;
 typedef struct Chanpipe Chanpipe;
-
-struct Input
-{
-	Mousectl *mc;
-	Keyboardctl *kc;
-};
 
 struct Ship
 {