Created
June 20, 2022 21:44
-
-
Save 9nut/aaa9b9b6a22d69996b75ccdc6e615c61 to your computer and use it in GitHub Desktop.
Example concurrent network requests using the Plan 9 threads library
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <u.h> | |
#include <libc.h> | |
#include <thread.h> | |
int STKSIZE = 2*1024; | |
struct SleepArgs { | |
long millies; | |
Channel *c; | |
}; | |
typedef struct SleepArgs SleepArgs; | |
void | |
sleeper(void *arg) | |
{ | |
SleepArgs *sa = arg; | |
Ioproc *io = ioproc(); | |
iosleep(io, sa->millies); | |
closeioproc(io); | |
send(sa->c, 0); | |
} | |
struct WorkArgs { | |
char *addr; | |
char *msg; | |
int mlen; | |
Channel *c; | |
}; | |
typedef struct WorkArgs WorkArgs; | |
void | |
worker(void *arg) | |
{ | |
WorkArgs *wa = arg; | |
char ret[128]; | |
Ioproc *io = ioproc(); | |
int fd = iodial(io, wa->addr, nil, nil, nil); | |
int hit = 0; | |
if(fd >= 0) { | |
if(iowrite(io, fd, wa->msg, wa->mlen) >= 0) { | |
if (ioread(io, fd, ret, sizeof(ret)) >= 0) { | |
hit = 1; | |
} | |
} | |
} | |
closeioproc(io); | |
sendul(wa->c, hit); | |
} | |
struct DispatchArgs { | |
long timeout; | |
char *addr; | |
char *data; | |
int dlen; | |
}; | |
typedef struct DispatchArgs DispatchArgs; | |
void | |
dispatcher(void *arg) | |
{ | |
enum { Sleeper, Worker }; | |
DispatchArgs *da = arg; | |
int st; | |
Alt a[] = { | |
{nil, nil, CHANRCV}, | |
{nil, &st, CHANRCV}, | |
{nil, nil, CHANEND}, | |
}; | |
a[Sleeper].c = chancreate(sizeof(int), 0); | |
a[Worker].c = chancreate(sizeof(int), 0); | |
SleepArgs sa = {da->timeout, a[Sleeper].c}; | |
threadcreate(sleeper, &sa, STKSIZE); | |
WorkArgs wa = {da->addr, da->data, da->dlen, a[Worker].c}; | |
threadcreate(worker, &wa, STKSIZE); | |
switch(alt(a)){ | |
case Sleeper: | |
print("time out\n"); | |
break; | |
case Worker: | |
if (st) { | |
print("success\n"); | |
} else { | |
print("failure\n"); | |
} | |
break; | |
default: | |
sysfatal("can't happen"); | |
} | |
} | |
/* | |
Examples: | |
./concio_ex -a 'tcp!bootes!echo' -t 1 -n 10 | |
./concio_ex -a 'tcp!52.43.121.77!9001' -t 1 -n 42 | grep success | wc -l | |
./concio_ex -a 'udp!52.43.121.77!10001' -t 3 -n 63 | grep success | wc -l | |
*/ | |
void | |
threadmain(int argc, char *argv[]) | |
{ | |
int nprocs = 80; // number of concurrent workers | |
char *addr = "udp!52.43.121.77!10001"; // hosted by digi.com | |
long tout = 1000; // default timeout 1s | |
char * f; | |
ARGBEGIN { | |
case 'n': | |
f = ARGF(); | |
if (f) nprocs = atoi(f); | |
break; | |
case 'a': | |
f = ARGF(); | |
if (f) addr = f; | |
break; | |
case 't': | |
f = ARGF(); | |
if (f) tout = atol(f) * 1000; | |
break; | |
default: | |
print("badflag('%c')", ARGC()); | |
exits("flag"); | |
} | |
ARGEND | |
DispatchArgs da = {tout,addr, "Echo this back", sizeof("Echo this back")}; | |
for(int i = 0; i < nprocs; i++){ | |
proccreate(dispatcher, &da, STKSIZE); | |
} | |
sleep(tout); | |
threadexitsall(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment