ref: 2b99422480d596ebc26921c87c6bb81a07949f3e
dir: /progs/etticker.c.ms/
.P1
.ps -1
.ti -1i
.B
.BX etticker.c
.ps +1
.CW
.ps -2
.vs .15i
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <thread.h>
enum { Npanels = 2 };
Channel*timerc; // of char*
Channel*consc; // of char*
Channel*tempc; // of char*
Channel*bcastc; // of char*
Channel*panelc[Npanels]; // of char*
.ps +2
.P2
.P1
.ps -2
.vs .15i
typedef struct PArg PArg;
struct PArg {
Channel* c; // to get new messages from
int fd; // to the panel's file.
};
.ps +2
.P2
.P1
.ps -2
.vs .15i
void
consreadthread(void*)
{
Biobuf bin;
char* ln;
threadsetname("consread");
Binit(&bin, 0, OREAD);
while (ln = Brdstr(&bin, '\en', 1))
sendp(consc, ln);
sendp(consc, nil);
Bterm(&bin);
threadexits(nil);
}
.ps +2
.P2
.P1
.ps -2
.vs .15i
void
bcastthread(void*)
{
char* msg;
int i;
threadsetname("bcast");
do {
msg = recvp(bcastc);
for (i = 0; i < Npanels; i++)
if (msg != nil)
sendp(panelc[i], strdup(msg));
else
sendp(panelc[i], nil);
free(msg);
} while(msg != nil);
threadexits(nil);
}
.ps +2
.P2
.P1
.ps -2
.vs .15i
void
panelthread(void* a)
{
PArg* arg = a;
char* msg;
threadsetname("panel");
while(msg = recvp(arg->c)){
write(arg->fd, msg, strlen(msg));
free(msg);
}
threadexits(nil);
}
.ps +2
.P2
.P1
.ps -2
.vs .15i
void
timerthread(void* a)
{
Channel* c = a;
ulong now;
Tm* tm;
char msg[10];
for(;;){
now = time(nil);
tm = localtime(now);
seprint(msg, msg+10, "%d:%d", tm->hour, tm->min);
sendp(c, strdup(msg));
sleep(60 * 1000);
}
}
.ps +2
.P2
.P1
.ps -2
.vs .15i
void
tempthread(void* a)
{
Channel* c = a;
char temp[10];
char last[10];
int fd, nr;
last[0] = 0;
fd = open("/dev/temp", OREAD);
if (fd < 0)
sysfatal("/dev/temp: %r");
for(;;){
nr = read(fd, temp, sizeof(temp) - 1);
if (nr <= 0)
sysfatal("can't read temp");
temp[nr] = 0;
if (strcmp(last, temp) != 0){
strcpy(last, temp);
sendp(c, strdup(temp));
}
sleep(60 * 1000);
}
}
.ps +2
.P2
.P1
.ps -2
.vs .15i
void
decoratorthread(void*)
{
char* lcons, *ltimer, * ltemp;
char* consmsg, *timermsg, *tempmsg;
char* msg;
Alt alts[] = {
{ timerc,&timermsg, CHANRCV },
{ consc, &consmsg, CHANRCV },
{ tempc, &tempmsg, CHANRCV },
{ nil, nil, CHANEND } };
lcons = strdup(""); ltimer = strdup(""); ltemp = strdup("");
for(;;){
msg = nil;
switch(alt(alts)){
case 0: // operation in alts[0] made
msg = smprint("%s (%s %s)\en",
lcons, timermsg, ltemp);
free(ltimer);
ltimer = timermsg;
break;
.ps +2
.P2
.P1
.ps -2
.vs .15i
case 1: // operation in alts[1] made
msg = smprint("%s (%s %s)\en",
consmsg, ltimer, ltemp);
free(lcons);
lcons = consmsg;
break;
.ps +2
.P2
.P1
.ps -2
.vs .15i
case 2: // operation in alts[2] made
msg = smprint("%s (%s %s)\en",
lcons, ltimer, tempmsg);
free(ltemp);
ltemp = tempmsg;
break;
}
sendp(bcastc, msg);
}
}
.ps +2
.P2
.P1
.ps -2
.vs .15i
void
threadmain(int, char*[])
{
int i;
PArg* arg;
timerc = chancreate(sizeof(char*), 0);
consc = chancreate(sizeof(char*), 0);
tempc = chancreate(sizeof(char*), 0);
proccreate(timerthread, timerc, 8*1024);
proccreate(consreadthread, consc, 16*1024);
proccreate(tempthread, tempc, 8*1024);
for (i = 0; i < Npanels; i++){
panelc[i] = chancreate(sizeof(char*), 0);
arg = malloc(sizeof(*arg));
arg->c = panelc[i];
arg->fd = 1; // to test the program.
proccreate(panelthread, arg, 8*1024);
}
bcastc = chancreate(sizeof(char*), 0);
threadcreate(decoratorthread, nil, 8*1024);
bcastthread(nil);
}
.ps +2
.P2