# It would be good if the basic coroutine support in nipl could be general, # and not dependent on "struct process" or anything. I don't see how that's # possible however. perhaps with macros? # I could implement "generators", which return a value each time, and keep # their pc in the data structure. no. # alt, assuming we still return pc, we could have a "resume" macro or inline # function that calls a process... # I think it would be better _not_ to have different pcs for different events, # rather to switch by an event code after the event is triggered. # add channels soon... use stdio.h struct process typedef int (*process_func)(process *p) struct process process_func f int pc void *data # pc == 0 means stop # (used to be pc == -1) # This means we can't distinguish "unstarted" from "stopped". # If this proves to be a problem, we can make "start" == 1. inline int resume(process *p) return p->pc = (*p->f)(p) int count_to_three(process *p) switch p->pc 0 printf("1\n") return 1 1 printf("2\n") return 2 2 printf("3\n") return 3 3 . return 0 struct count_to_n_data int n int c int count_to_n(process *p) count_to_n_data *d = (count_to_n_data *)p->data switch p->pc 0 d->c = 1 while d->c <= d->n printf("%d\n", d->c) ++ (d->c) return 1 1 . return 0 # will have to consider how to implement "child" or "sub-" processes using namespace std use deque int main() process c3 = { count_to_three, 0 } while resume(&c3) count_to_n_data d1, d2 process cn1 = { count_to_n, 0, &d1 } process cn2 = { count_to_n, 0, &d2 } d1.n = 10 d2.n = 15 deque q q.push_back(&cn1) q.push_back(&cn2) while !q.empty() process *p = q.front() q.pop_front() if resume(p) q.push_back(p) return 0