And now the basic support is there to use them for Stdio.File objects.
Stdio.File now has a new nonblocking mode: Buffered I/O
In this mode the file object maintains two buffers, one for input and one for output.
The read callback will get the buffer as the second argument, and data that the user does not read from that buffer is kept until the next time data arrives from the file (this means you do not have to do your own buffering of input)
The output buffer is, unsurprisingly, used to output data from.
This has at least three somewhat convenient effects:
o The write callback will now receive that buffer as a second argument. You just add data to it to write it.
o Adding data to the buffer when /not/ in the write callback will still trigger sending of data if no write callback is pending.
o Your write callback will not be called until the buffer is actually empty.
[...]
Great addition, although I'm a bit uncertain about whether it would be more suitable to instead add it to Stdio.FILE.
One thing that I'm missing is a way to enqueue a close on write done.
Hmm... Maybe the something like the following would work?
fd->set_write_callback(Function.uncurry(Function.uncurry( Function.curry(fd->close, "w"))));
But I don't like the circular reference...
Currently read() and write() are not in any way modified by having buffered output enabled, if you interact directly with the file object it will bypass the buffer. I am unsure if this is a good idea or not.
It doesn't sound like a good idea, since it would cause interleaving between the manual and automatic calls at random places in the stream, and it would be complicated to recover in a deterministic way.
As a comparison SSL.File also has buffers on both read and write (I hope to be able to replace these with IOBuffers soon), and there read(), write() and close() all go via the buffers.
Then there's of course the separate problem with out of band data...
/grubba