# back to C! use stdio.h use deque.h use error.h # It would be good to be able to instantiate a # special deque or vector of size 2, 4 or 8, for # example, and share that among different types. # Would need some sort of "macro include" facility # to do that, maybe something as simple as: # define N 4 # # # or even: # N=4 # or (4) deque q sched_init() deque_init(&q, sizeof(process *), 8) typedef int (*process_func)(process *p) struct process process_func f int pc process_init(process *p, process_func f) p->f = f p->pc = 1 # it'd be nice to have a struct constructor syntax? # struct process(f) # process_func f # int pc = 1 # # this would automatically create process_init and # call it when the struct was declared like: # process p(f) # # ??? start(process *p) *(process **)deque_push(&q) = p int resume(process *p) int rv = (*p->f)(p) if rv p->pc = rv return rv run() while q.size step() step() process *p = *(process **)deque_element(&q, 0) deque_shift(&q) if resume(p) start(p) struct rendezvous process *waiting rendezvous_init(rendezvous *r) r->waiting = NULL # here are the general rendezvous methods: # meet - if the partner is here, returns 0, # otherwise we wait for the partner to arrive, returns 1, # (caller must then yield) int meet(rendezvous *r, process *p) int must_wait = !r->waiting if must_wait r->waiting = p return must_wait # pass - give control to the partner # (this works whether or not they are here already) pass(rendezvous *r, process *p) if r->waiting start(r->waiting) r->waiting = p # part - finish the rendezvous # (this assumes they are here) part(rendezvous *r) start(r->waiting) r->waiting = NULL # peer - get the partner's process pointer # or NULL if they are not here process *peer(rendezvous *r) return r->waiting # here - check if the partner is here int here(rendezvous *r) return peer(r) != NULL struct channel_int rendezvous r int data # we could do with Plan 9 cc's struct inheritance # my namespaces feature will be better, though! struct count_to_three process p channel_int *out count_to_three_init(count_to_three *x, channel_int *out) process_init(&x->p, count_to_three_f) x->out = out int count_to_three_f(process *p) count_to_three *d = (count_to_three *)p rendezvous *out_r = &d->out->r switch p->pc 1 if meet(out_r, p) p->pc = 2 return 0 2 d->out->data = 1 part(out_r) if meet(out_r, p) p->pc = 3 return 0 3 d->out->data = 2 part(out_r) if meet(out_r, p) p->pc = 4 return 0 4 d->out->data = 3 part(out_r) return 0 struct printer process p channel_int *in printer_init(printer *x, channel_int *in) process_init(&x->p, printer_f) x->in = in int printer_f(process *p) printer *d = (printer *)p rendezvous *in_r = &d->in->r switch p->pc 1 while 1 p->pc = 2 pass(in_r, p) return 0 2 printf("%d\n", d->in->data) return 0 struct count_to_n process p channel_int *out int n count_to_n_init(count_to_n *x, channel_int *out, int n) process_init(&x->p, count_to_n_f) x->out = out x->n = n int count_to_n_f(process *p) count_to_n *d = (count_to_n *)p rendezvous *out_r = &d->out->r switch p->pc 1 if meet(out_r, p) p->pc = 2 return 0 2 d->out->data = 1 part(out_r) while d->out->data < d->n if meet(out_r, p) p->pc = 3 return 0 3 ++ (d->out->data) part(out_r) return 0 int main() sched_init() channel_int ch rendezvous_init(&ch.r) count_to_three c3 count_to_three_init(&c3, &ch) printer pr printer_init(&pr, &ch) start(&c3.p) start(&pr.p) run() count_to_n cn count_to_n_init(&cn, &ch, 15) start(&cn.p) run() return 0