iostream examples

Buffering exposed

As the name suggests streambufs may implement the sequence abstraction by buffering between the source and sink of characters. This results in an unfortunate pun. The word ``buffer'' is frequently used informally to designate a streambuf, but it is also used to describe the chunking of characters. Thus, the oxymoron ``unbuffered buffer'' refers to a streambuf in which characters are passed to the ultimate consumer as soon as they are stored, and obtained from the ultimate producer whenever they are retrieved.

In light of the buffering provided by streambufs, the reader will not be surprised to discover that arrays of characters are used in the implementation. The streambuf class contains some member functions that make the presence of such arrays visible to the program. With some effort, they might be used to ``break the abstraction,'' but the intended purpose is to deal with the delays implicit in buffering.

The earlier example using sgetn() and sputn() to copy from in to out waits until Bufsize characters become available (or the end of the sequence is reached) before passing any to out. If the source of characters has delays (e.g., it is a person typing at a terminal) and we want the characters to be passed on as soon as they become available; the program might use operations on single characters instead, or it might use an adaptive method such as:

   static const int Bufsize = 1024 ;
   char buf[Bufsize] ;
   int p, g ;
   do {
   	in->sgetc() ;		// force a character in buffer
   	g = in->in_avail() ;
   	if ( g > Bufsize ) g = Bufsize ;
   	g = in->sgetn(buf,g) ;
   	p = out->sputn(buf,g) ;
   	out->sync() ;
   	if ( p!=g ) error("output error");
   	} while ( g > 0 )
in_avail returns the number of characters immediately available in the array. Calling sgetc() first forces there to be at least one such character (unless the get pointer is at the end of the sequence). Recall that sgetc() returns the next character, but doesn't move the get pointer. The code calls sync() after it has put characters into out, thus causing these characters to be sent to the ultimate consumer.

In some circumstances, such as when streambufs are being used for interprocess messages, the chunks in which characters are produced and consumed may have significance. The above preserves these chunks provided they are less than Bufsize and they fit into the arrays of in and out. To ensure that this latter condition is met, the code should provide large enough arrays explicitly with:

   char ibuf[Bufsize+8], obuf[Bufsize+8] ;
   in->setbuf(ibuf,sizeof(ibuf)) ;
   out->setbuf(obuf,sizeof(obuf)) ;
The calls to setbuf() should be done before any fetches or stores are done. The arrays are eight larger than required by the largest chunk to allow for various overheads. Of course, this code behaves properly only when in delivers the characters in the appropriate chunks.
Next topic: Using streambufs in streams
Previous topic: The sequence abstraction

© 2004 The SCO Group, Inc. All rights reserved.
UnixWare 7 Release 7.1.4 - 27 April 2004