|
- Change the BPending system to work in LIFO mode (rather than FIFO).
- Modify I/O interfaces ({Packet,Stream}{Pass,Recv}Interface) to push I/O calls (Send/Recv, Done) to the queue, instead of calling the handlers directly.
- Port everything to work with the new design.
- Minor beautifications all around as part of the porting.
This new design fits very well into the data flow system. It greatly simplifies writing I/O modules by making I/O programming more declarative.
For instance:
- No more explicit checking what happened as a result of the I/O operation (e.g. was the object freed?) and during it (can it call this function from inside?).
- There is no longer a clear distinction between an I/O operation completing immediately or having to wait for its completion (read on for explanation).
Each time control returns to the reactor, the reactor pops a job off the top of the job list and executes it. A job may push further jobs while it's executing.
The popping of some job from the list and pushing of new jobs from this job's handler can be seen as a transformation of a job into other jobs. Let's
call these jobs the "transformation" of a job. And let's the job, its transformation, transformations of the transformation, and so on recursively, the
"transformation closure"
of a job.
Now suppose a Send operation is pushed to the job queue.
The operation can be considered completed immediately if its transformation closure contains the corresponding Done job.
Similarly, an operation can be considered blocked on external I/O if the job list empties before the Done job is pushed.
(note this leaves a third possibility...)
On the other hand, this design requires changes in the client and server programs, because it becomes impossible to send more than one packet
to a send buffer directly in response to a single input. To, for instance, send two packets into into the same send buffer in response to an input,
you need to first schedule sending the second one, then send the first one.
|