I have been thinking about the design of nsIChannel::AsyncWrite.
Currently, we expect the user to provide a nsIInputStream as the source
of data to be written to the channel. This effectively requires the
data to be buffered before it can be written to the channel. In the
case of form posting, this buffer is a temporary file.
From a high level perspective this buffering of data seems unnecessary
and wasteful. It should be possible to write the form data directly to
the underlying transport instead of requiring the use of a temporary
buffer. That is, if the transport were given control over when data
is actually written to the channel, then buffering could easily be
eliminated.
How would this work? Well... the transport can fire a callback when a
chunk of data could be written without blocking. This callback could be
propogated to the caller of AsyncWrite in some fashion. The implementor
of that callback would then supply the chunk of data.
This new design is very much in line with the design of AsyncRead. For
AsyncRead, the transport fires a callback whenever there is a chunk of
data to be read. In this manner, the transport drives the entire
process of reading data from a channel. My proposal for AsyncWrite is
to make it similarly drive the entire process of writing data to a
channel.
Currently AsyncWrite is declared as:
void AsyncWrite(in nsIInputStream source,
in nsIStreamObserver observer,
in nsISupports context);
The observer is notified when the write starts and stops. The context
is passed as an opaque parameter to the observer methods.
My proposal is to change this to:
void AsyncWrite(in nsIStreamWriter writer,
in nsISupports context);
with
interface nsIStreamWriter : nsIStreamObserver
{
void OnDataWriteable(in nsIChannel channel,
in nsISupports context,
in nsIOutputStream output,
in unsigned long offset,
in unsigned long count);
};
This would provide the interface necessary to allow AsyncWrite to be
transport driven.
BTW: the name nsIStreamWriter is totally up to debate. It isn't exactly
symmetric with nsIStreamListener used by AsyncRead. Perhaps
nsIStreamProvider would be better, or perhaps nsIStreamListener should
be changed to nsIStreamReader? Or, what about nsIAsyncWriter and
nsIAsyncReader?
At any rate, I'd really like to get some feedback from people regarding
these changes. I believe that it is a good idea. To me, it is simply
more consistent with the concept of asynchronous channel io, and I
believe that it would lead to more efficient protocol and application
implementations.
Darin