C++ Ostream Buffers

ISO/IEC JTC1 SC22 WG21 N3750 - 2013-09-01

Lawrence Crowl, Lawrence@Crowl.org

Introduction
Solution
Wording
    27.8.1 Overview [string.stream.overview]
    27.8.8 Class template ostream_buffer [ostream.buffer]
    27.8.8.1 Constructor [ostream.buffer.ctor]
    27.8.8.2 Destructor [ostream.buffer.dtor]
    27.8.8.3 Member function [ostream.buffer.memfn]
References

Introduction

At present, stream output operations guarantee that they will not produce race conditions, but do not guarantee that the effect will be sensible. Some form of external synchronization is required. Unfortunately, without a standard mechanism for synchronizing, independently developed software will be unable to synchronize.

N3535 C++ Stream Mutexes proposed a standard mechanism for finding and sharing a mutex on streams. At the Spring 2013 standards meeting, the Concurrency Study Group requested a change away from a full mutex definition to a definition that also enabled buffering.

N3678 C++ Stream Guards proposed a standard mechanism for batching operations on a stream. That batching may be implemented as mutexees, as buffering, or some combination of both. It was the response to the Concurrency Study Group. A draft of that paper was reviewed in the Library Working Group, who found too many open issues on what was reasonably exposed to the 'buffering' part.

N3665 Uninterleaved Sring Output Streaming proposed making streaming of strings of length less than BUFSIZ appear uninterleaved in the output. It was a "minimal" functionality change to the existing standard to address the problem. The full Committee chose not to adopt that minimal solution.

The general concensus in the July 2013 meeting of the Concurrency Study Group was that buffering should be explicit. This paper proposes such an explicit buffering.

Solution

We propose an ostream_buffer, that provides access to a matching basic_ostringstream for buffering output operations. The ostream_buffer, will atomically transfer the contents of the basic_ostringstream to an ostream on destruction of the ostream_buffer.

The transfer on destruction simplifies the code and ensures at least some output in the presence of an exception.

The intent is that the ostream_buffer is an automatic-duration variable with a relatively small scope which constructs the text to appear uninterleaved. For example,

....
{
  std::ostream_buffer<std::ostream> bout(std::cout);
  bout.stream() << "Hello, " << "World!" << std::endl;
}
....

The wording below permits implementation of ostream_buffer with either a stream_mutex from N3535 or with implementations suitable for N3665, e.g. with Posix file locks [PSL]

Wording

This wording is relative to N3691.

27.8.1 Overview [string.stream.overview]

Edit within paragraph 1 as follows.

The header <sstream> defines four class templates and eight types that associate stream buffers with objects of class basic_string, as described in 21.3. It also defines a class template to buffer a basic_ostringstream into an ostream.

Edit within the synopsis as follows.

  template <class charT, class traits = char_traits<charT>,
        class Allocator = allocator<charT> >
    class basic_stringstream;
  typedef basic_stringstream<char> stringstream;
  typedef basic_stringstream<wchar_t> wstringstream;

  template <class Stream>
    class ostream_buffer;
}

27.8.8 Class template ostream_buffer [ostream.buffer]

Add a new section.

template <class Stream>
  class ostream_buffer;

The class template ostream_buffer<Stream> supports buffering into a basic_ostringstream and then automatically transfering the contents of the basic_ostringstream to an ostream.

[Example:

....
{
  std::ostream_buffer<std::ostream> bout(std::cout);
  bout.stream() << "Hello, " << "World!" << std::endl;
}
....

end example]

27.8.8.1 Constructor [ostream.buffer.ctor]

Add a new section.

ostream_buffer(Stream& stream);

Effects: Constructs an internal basic_ostringstream.

27.8.8.2 Destructor [ostream.buffer.dtor]

Add a new section.

~ostream_buffer();

Effects: Transfers the contents of the internal basic_ostringstream to the Stream specified in the constructor as an indivisible uninterleaved sequence of characters, with respect to all other uses of ostream_buffer on that Stream.

Synchronization: May or may not acquire a mutex while transfering characters.

27.8.8.3 Member function [ostream.buffer.memfn]

Add a new section.

std::basic_ostringstream<typename Stream::char_type, typename Stream::traits_type>& stream();

Returns: A reference to the internal basic_ostring.

References

[PSL]
The Open Group Base Specifications Issue 6, IEEE Std 1003.1, 2004 Edition, functions, flockfile, http://pubs.opengroup.org/onlinepubs/009695399/functions/flockfile.html