On Fri, Sep 23, 2011 at 4:32 AM, Kristian Nielsen <knielsen@knielsen-hq.org> wrote:
MARK CALLAGHAN <mdcallag@gmail.com> writes:
Why does this need to save/restore thread contexts (setcontext, etc)? I think that if the library is that hard to change then it should be fixed or a simpler solution should be attempted.
In general, when implementing non-blocking semantics like this, there are two main approaches:
1. Write the code in event-driven style. This means using some kind of state machine or message passing (or both) rather than normal nested calls. Whenever code needs to do I/O, or call another function that might do I/O, the current state is manually saved to some struct and control returns to the caller. When the I/O completes control must continue in the next state of the state machine or handler of completion message.
2. Use co-routines (also called fibers or light-weight threads or whatever). The code is written in normal style with nested calls. For operations that need to do I/O, a co-routine is spawned to run the operation; when waiting for I/O the co-routine is suspended, and resumed again when I/O completes.
The main reason I choose (2) is similar to what RethinkDB describe here:
http://blog.rethinkdb.com/improving-a-large-c-project-with-coroutines http://blog.rethinkdb.com/making-coroutines-fast
Basically, (1) is nice for writing quick IRC bots and the like, but as the complexity of the problem grows, the event-driven code becomes very hard to maintain and extend.
For adding non-blocking to an existing library like libmysql, there is the added advantage that the change can be much less intrusive, as we can avoid re-writing parts of the existing code into event-driven style.
Why isn't it sufficient to do a sequence of non-blocking reads to buffer enough data to produce a query result and then process the received data? That doesn't require getcontext/setcontext. -- Mark Callaghan mdcallag@gmail.com