> I would like to build a rich "process api" that can fork, merge, pause, yield, yield until, drop while, synchronize, wait (latch), react according to events. I feel every distributed systems builds this again and again.
Years ago I attempted to build an experimental language with first-class resumable functions. Every function can be invoked by the caller through a special reference type called "quaint". The caller can resume or stop the execution of the function either after reaching a timeout, or after passing a "wait label":
https://github.com/bbu/quaint-lang
A typical CPU-intensive example where preemption is done by the caller after a certain timeout:
entry
{
fibq: quaint(u32) = ~fibonacci(32 as u32);
ps("At start: "), pu8(fibq@start), pnl();
iter: u32 = 0:u32;
do {
wait fibq for 1000 msec;
ps("Iteration "), pu32(iter++), pnl();
} while !fibq@end;
ps("At end: "), pu8(fibq@end), pnl();
const value: u32 = *fibq;
ps("Reaped value: "), pu32(value), pnl();
}
fibonacci(number: u32): u32
{
if number == 0:u32 || number == 1:u32 {
return number;
} else {
return fibonacci(number - 1:u32) + fibonacci(number - 2:u32);
}
}
An example that uses "wait labels" to suspend execution of the callee at certain points:
entry
{
q: quaint(u64) = ~pointless_function();
wait q until pointless_function::label_a;
ps("At label_a: "), pu8(q@pointless_function::label_a), pnl();
wait q until pointless_function::label_b;
ps("At label_b: "), pu8(q@pointless_function::label_b), pnl();
wait q until pointless_function::label_c;
ps("At label_c: "), pu8(q@pointless_function::label_c), pnl();
wait q;
ps("At end: "), pu8(q@end), pnl();
ps("Result: "), pu64(*q), pnl();
}
pointless_function: u64
{
i: u64 = 0 as u64;
while ++i