Version française
Home     About     Download     Resources     Contact us    
Browse thread
[Caml-list] Flush behavior of baseic I/O class type
[ Home ] [ Index: by date | by threads ]
[ Search: ]

[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: -- (:)
From: John Prevost <j.prevost@g...>
Subject: Re: [Caml-list] Flush behavior of baseic I/O class type
> It may be ok for non-blocking I/O, but it will cause "busy-waiting" ,
> so perhaps a user does not like it.  Moreover, for example, if the
> channel is actually a filter, and it needs more inputs to determine
> the next output, then it will stuck forever.  (See the case of the
> multibyte charcter code converter in the previous mail)
> 
> The easiest way (from the implementer's point of the view) would be
> 1), or 1') do the best effort to output, but nothing is guaranteed.
> However I'm afraid that it will cause a subtle I/O bug.

If there is an explicit "flush" call, then the only reasonable thing
to do is to block until everything that may be written has been
written.  In fact, the flush call on a filter should write everything,
and then tell the next level down to also flush.

For the MBCS implementation that you describe, you're right that
things are slighlty more complicated.  In that case, the MBCS
implementation could choose to *either* "break" the incomplete
multi-byte character somehow (in a similar way to how it would have to
somehow deal with an incomplete multi-byte character when the file is
closed), or it might choose to flush everything up to that incomplete
multi-byte character, but keep the incomplete character in the buffer.
 My choice would probably be to "break" it.  Either way, the
implementation should describe what it does.

Finally, you mention difficulties with blocking vs. non-blocking I/O
here.  You are correct that there is a problem with flush in this
case--and the problem (to me) seems to be in the API design for these
I/O classes.  If you look at the design for Java I/O, you'll notice
that the java.io output classes contain flush methods but do not
support non-blocking I/O, and the java.nio classes support
non-blocking I/O but do not support flush methods.  In C, the fflush
call "may also fail and set errno for any of the errors specified for
the routine write(2)."  And write may return EAGAIN in order to
indicate that the write would block.  And finally, it's worth noting
that the "write" family of calls make a lot more sense in a
non-blocking situation than the "fwrite" family of calls.

So I would suggest that the solution for non-block I/O here is that
the API should be changed.  One choice is that either flush must be
able to return a result or it must be able to raise an exception that
indicates that not all of the output has yet been written (and it's
important that callers don't see the "broken MBCS character" above as
something they can re-try).

The other choice is that there should be a slightly different set of
operations on blocking and non-blocking streams.  In that case:

Non-blocking output operations should always be attempted immediately,
and return a result indicating that there is a problem if they cannot
write everything.  Non-blocking I/O should therefore not have a flush
operation. (If I am writing an application that uses non-blocking I/O,
this is the API I want: I am doing my own buffering, and need to know
exactly what has been written and what still needs to be written.)

Blocking output should never return until every character has either
been written completely, or has been placed in an intermediate buffer.
 And the flush operation should block until all output has been
written (and the MBCS implementor must make the choice I described
above.)  (If I am writing an application that uses blocking I/O, this
is again the API I want: I do not want to worry about buffering, and
either don't care about blocking or am handling it with multiple
threads.  When I want to make sure that everything has been written, I
am happy to call flush.)

Finally, one might argue that if an *output* channel of multi-byte
characters has received a partial character, then a type error has
occurred.  I understand, however, that there may be issues of
expediency that prevent you from making each character atomic.

John.

-------------------
To unsubscribe, mail caml-list-request@inria.fr Archives: http://caml.inria.fr
Bug reports: http://caml.inria.fr/bin/caml-bugs FAQ: http://caml.inria.fr/FAQ/
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners