Co-routines are very similar to what I'm already doing, really. For fairly linear code one can easily end up with co-routine functions that are multi-thousand lines of code long -- see PuTTY for example.
> Update the state object associated with the I/O event in place (and unregister/re-register it with the event loop as needed)?
I have a simple data structure to represent the continuation, which is really more like a closure, consisting of `{fd, data, handler_function}` (this being C). Events are typically one-shots. When queuing I/O I just update the handler_function of that struct and then register the one-shot event with epoll, re-using this "closure" object. When it comes time to close a connection and we're done handling events we free (or, rather, put on a free-list) the closure, and destruct the client data structure.
To be fair, continuations are also the classic way to implement coroutines in languages that don't have them. Probably should've mentioned that in my original comment...
Alternatives include:
Co-routines are very similar to what I'm already doing, really. For fairly linear code one can easily end up with co-routine functions that are multi-thousand lines of code long -- see PuTTY for example.> Update the state object associated with the I/O event in place (and unregister/re-register it with the event loop as needed)?
I have a simple data structure to represent the continuation, which is really more like a closure, consisting of `{fd, data, handler_function}` (this being C). Events are typically one-shots. When queuing I/O I just update the handler_function of that struct and then register the one-shot event with epoll, re-using this "closure" object. When it comes time to close a connection and we're done handling events we free (or, rather, put on a free-list) the closure, and destruct the client data structure.