After thinking more about it, I think I now see the purpose of this architecture, and it is indeed very interesting and appealing.
I’m not able to visualize how to apply it to blocking I/O problems, though. Say you have a game that reads the keyboard for input, and you implement it like this, Julia-style, in pseudocode:
create a channel;
@async while True
k = read keyboard # this blocks until a key is pressed
put!(k,channel) # put the key in the channel
end
end
# main game loop
function run_game()
while True
do game stuff;
yield(); # give the async task a chance to run (a goto in disguise!)
if channel is not empty
k = take!(channel)
take action required by k
end
end
end
run_game();
With this approach, the code to read the keyboard runs asynchronously but I don’t expect it to ever complete! If I put it in a nursery inside run_game
, then the game will block forever. Maybe the solution is to put both in a “top-level” nursery?