Skip to content

Instantly share code, notes, and snippets.

@9nut
Created June 20, 2022 21:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 9nut/aaa9b9b6a22d69996b75ccdc6e615c61 to your computer and use it in GitHub Desktop.
Save 9nut/aaa9b9b6a22d69996b75ccdc6e615c61 to your computer and use it in GitHub Desktop.
Example concurrent network requests using the Plan 9 threads library
#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