<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
 "http://www.w3.org/TR/html4/strict.dtd">
<html><head>

<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">

<style type="text/css">

body {
  color: #000000;
  background-color: #FFFFFF;
}

del {
  text-decoration: line-through;
  color: #8B0040;
}
ins {
  text-decoration: underline;
  color: #005100;
}

p.example {
  margin: 2em;
}
pre.example {
  margin: 2em;
}
div.example {
  margin: 2em;
}

code.extract {
  background-color: #F5F6A2;
}
pre.extract {
  margin: 2em;
  background-color: #F5F6A2;
  border: 1px solid #E1E28E;
}

p.function {
}

p.attribute {
  text-indent: 3em;
}

blockquote.std {
  color: #000000;
  background-color: #F1F1F1;
  border: 1px solid #D1D1D1;
  padding: 0.5em;
}

blockquote.stddel {
  text-decoration: line-through;
  color: #000000;
  background-color: #FFEBFF;
  border: 1px solid #ECD7EC;
  padding: 0.5em;
}

blockquote.stdins {
  text-decoration: underline;
  color: #000000;
  background-color: #C8FFC8;
  border: 1px solid #B3EBB3;
  padding: 0.5em;
}

table {
  border: 1px solid black;
  border-spacing: 0px;
  margin-left: auto;
  margin-right: auto;
}
th {
  text-align: left;
  vertical-align: top;
  padding: 0.2em;
  border: none;
}
td {
  text-align: left;
  vertical-align: top;
  padding: 0.2em;
  border: none;
}

</style>

<title>C++ Ostream Buffers</title>
</head>
<body>
<h1>C++ Ostream Buffers</h1>

<p>
ISO/IEC JTC1 SC22 WG21 N3978 - 2014-05-26
</p>

<p>
Lawrence Crowl, Lawrence@Crowl.org<br>
Peter Sommerlad, Peter.Sommerlad@hsr.ch
</p>

<p>
<a href="#Introduction">Introduction</a><br>
<a href="#Solution">Solution</a><br>
<a href="#Wording">Wording</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#string.stream.overview">27.8.1 Overview [string.stream.overview]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ostream.buffer">27.8.8 Class template <code>basic_ostream_buffer</code> [ostream.buffer]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ostream.buffer.ctor">27.8.8.1 Constructor [ostream.buffer.ctor]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ostream.buffer.dtor">27.8.8.2 Destructor [ostream.buffer.dtor]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ostream.buffer.mfun">27.8.8.2 Member Functions [ostream.buffer.mfun]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ostream.noteflush.stringbuf">27.8.9 Class template <code>noteflush_stringbuf</code> [ostream.noteflush.stringbuf]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#ostream.noteflush.stringbuf.mfun">27.8.9.1 Member Functions [ostream.noteflush.stringbuf.mfun]</a><br>
<a href="#Revisions">Revisions</a><br>
<a href="#References">References</a><br>
</p>


<h2><a name="Introduction">Introduction</a></h2>

<p>
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.
</p>

<p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html">
N3535 C++ Stream Mutexes</a>
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.
</p>

<p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3678.html">
N3678 C++ Stream Guards</a>
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.
</p>

<p>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3665.html">
N3665 Uninterleaved Sring Output Streaming</a>
proposed making streaming of strings of length less than <code>BUFSIZ</code>
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.
</p>

<p>
The general consensus in the July 2013 meeting of the Concurrency Study Group
was that buffering should be explicit.
This paper proposes such an explicit buffering.
</p>


<h2><a name="Solution">Solution</a></h2>

<p>
We propose a <code>basic_ostream_buffer</code>,
that provides access to a matching <code>basic_ostringstream</code>
for buffering output operations.
The <code>basic_ostream_buffer</code>,
will atomically transfer the contents
of the <code>basic_ostringstream</code> to an <code>ostream</code>
on destruction of the <code>basic_ostream_buffer</code>.
</p>

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

<p>
The intent is that the <code>basic_ostream_buffer</code>
is an automatic-duration variable
with a relatively small scope
which constructs the text to appear uninterleaved.
For example,
</p>
<pre class="example">
....
<code>{
  std::ostream_buffer bout(std::cout);
  bout &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; std::endl;
}</code>
....
</pre>

<p>
The wording below
permits implementation of <code>basic_ostream_buffer</code>
with either a <code>stream_mutex</code>
from
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3535.html">
N3535</a>
or with implementations suitable for
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3665.html">
N3665</a>,
e.g. with Posix file locks
<a href="#PSL">[PSL]</a>
</p>


<h2><a name="Wording">Wording</a></h2>

<p>
This wording is relative to N3691.
</p>


<h3><a name="string.stream.overview">27.8.1 Overview [string.stream.overview]</a></h3>

<p>
Edit within paragraph 1 as follows.
</p>

<blockquote class="std">
<p>
The header <code>&lt;sstream&gt;</code>
defines four class templates and eight types
that associate stream buffers with objects
of class <code>basic_string</code>, as described in 21.3.
<ins>
It also defines a class template <code>basic_ostream_buffer</code>
to buffer a <code>basic_ostringstream</code>
into an <code>ostream</code>
and the corresponding string buffer.
</ins>
</blockquote>

<p>
Edit within the synopsis as follows.
</p>

<blockquote class="std">
<pre><code>
  template &lt;class charT, class traits = char_traits&lt;charT&gt;,
        class Allocator = allocator&lt;charT&gt; &gt;
    class basic_stringstream;
  typedef basic_stringstream&lt;char&gt; stringstream;
  typedef basic_stringstream&lt;wchar_t&gt; wstringstream;

<ins>  template &lt;class charT,
            class traits = std::char_traits&lt;charT&gt;,
            class Allocator = std::allocator&lt;charT&gt; &gt;
    class basic_ostream_buffer
  typedef basic_ostream_buffer&lt;char&gt; ostream_buffer;
  typedef basic_ostream_buffer&lt;wchar_t&gt; wostream_buffer;</ins>

<ins>  template &lt;class charT,
            class traits = std::char_traits&lt;charT&gt;,
            class Allocator = std::allocator&lt;charT&gt; &gt;
    class noteflush_stringbuf
  typedef basic_ostream_buffer&lt;char&gt; ostream_buffer;
  typedef basic_ostream_buffer&lt;wchar_t&gt; wostream_buffer;</ins>

</code></pre>
</blockquote>


<h3><a name="ostream.buffer">27.8.8 Class template <code>basic_ostream_buffer</code> [ostream.buffer]</a></h3>

<p>
Add a new section.
</p>

<blockquote class="stdins">
<pre><code>template &lt;class charT,
          class traits = std::char_traits&lt;charT&gt;,
          class Allocator = std::allocator&lt;charT&gt; &gt;
class basic_ostream_buffer
  : public std::basic_ostringstream&lt;charT,traits,Allocator&gt;
{
  public:
  typedef charT                          char_type;
  typedef traits                         traits_type;
  typedef typename traits_type::int_type int_type;
  typedef typename traits_type::pos_type pos_type;
  typedef typename traits_type::off_type off_type;
  typedef Allocator                      allocator_type;
  typedef std::basic_string&lt;char_type, traits_type, allocator_type&gt;
          string_type;

  basic_ostream_buffer(basic_ostream_buffer &amp;osb);
  explicit basic_ostream_buffer(std::basic_ostream&lt;charT,traits&gt; &amp;os);
  ~basic_ostream_buffer();
};
</code></pre>

<p>
The class template <code>basic_ostream_buffer</code>
supports buffering into a <code>noteflush_stringbuf</code>
and then
indivisibly transfering the contents of the <code>noteflush_stringbuf</code>
to a <code>basic_ostream</code>.
</p>

<p>
[<i>Example:</i>
</p>
<pre class="example">
....
<code>{
  std::ostream_buffer bout(std::cout);
  bout &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; std::endl;
}</code>
....
</pre>
<p>
&mdash;<i>end example</i>]
</p>
</blockquote>


<h3><a name="ostream.buffer.ctor">27.8.8.1 Constructor [ostream.buffer.ctor]</a></h3>

<p>
Add a new section.
</p>

<blockquote class="stdins">

<dl>

<dt><code>basic_ostream_buffer(basic_ostream_buffer &amp;osb);</code></dt>
<dd>

<p><i>Effects:</i>
Constructs a <code>noteflush_stringbuf</code>.
May construct a mutex.
</p>

<dt><code>basic_ostream_buffer(std::basic_ostream&lt;charT,traits&gt; &amp;os);</code></dt>
<dd>

<p><i>Effects:</i>
Constructs a <code>noteflush_stringbuf</code>.
May construct a mutex.
</p>

</dd>
</dl>

</blockquote>


<h3><a name="ostream.buffer.dtor">27.8.8.2 Destructor [ostream.buffer.dtor]</a></h3>

<p>
Add a new section.
</p>

<blockquote class="stdins">

<dl>

<dt><code>~basic_ostream_buffer();</code></dt>
<dd>

<p><i>Effects:</i>
Transfers the contents of the <code>noteflush_stringbuf</code>
to the stream specified in the constructor
as an indivisible uninterleaved sequence of characters,
with respect to all other uses of <code>basic_ostream_buffer</code>
on that stream.
If and only if a flush was requested on the <code>noteflush_stringbuf</code>,
the stream will be flushed.
May destroy a lock.
</p>

<p><i>Synchronization:</i>
May or may not acquire a mutex
while transfering characters.
</p>

</dd>
</dl>

</blockquote>


<h3><a name="ostream.buffer.mfun">27.8.8.3 Member Functions [ostream.buffer.mfun]</a></h3>

<p>
Add a new section.
</p>

<blockquote class="stdins">

<dl>

<dt><code>void clear_for_reuse();</code></dt>
<dd>

<p><i>Effects:</i>
As if the <code>ostream_buffer</code> were destroyed and recreated.
</p>

<p><i>Synchronization:</i>
May or may not acquire a mutex
while transfering characters.
</p>

</dd>
</dl>

</blockquote>


<h3><a name="ostream.noteflush.stringbuf">27.8.9 Class template <code>noteflush_stringbuf</code> [ostream.noteflush.stringbuf]</a></h3>

<p>
Add a new section.
</p>

<blockquote class="stdins">

<pre><code>template &lt;class charT, class traits, class Allocator&gt;
class noteflush_stringbuf
  : public std::basic_stringbuf&lt;charT,traits,Allocator&gt;
{
  public:
    using std::basic_stringbuf&lt;charT, traits, Allocator&gt;::basic_stringbuf;
    bool needsflush = false;
    void clear();
  protected:
    virtual int sync();
};
</code></pre>

<p>
The class template <code>noteflush_stringbuf</code>
behaves as a <code>basic_stringbuf</code>
except that flushes are only noted instead of effective.
</p>

</blockquote>


<h3><a name="ostream.noteflush.stringbuf.mfun">27.8.9.1 Member Functions [ostream.noteflush.stringbuf.mfun]</a></h3>

<p>
Add a new section.
</p>

<blockquote class="stdins">

<dl>

<dt><code>void clear();</code></dt>
<dd>

<p><i>Effects:</i>
Empties the contents.
</p>

<dt><code>int sync();</code></dt>
<dd>

<p><i>Effects:</i>
Notes the occurence of a flush in <code>needsflush</code>.
</p>

<p><i>Returns:</i>
0.
</p>

</dd>
</dl>

</blockquote>



<h2><a name="Revisions">Revisions</a></h2>

<p>
This paper revises
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3892.html">
N3892 C++ Ostream Buffers</a>
</p>

<ul>

<li><p>
Flush the ostream if and only if the <code>ostream_buffer</code> was flushed.
</p></li>

<li><p>
Add the <code>clear_for_reuse</code> function.
</p></li>

<li><p>
Change the design from inheriting from <code>basic_ostream</code>
to using a <code>noteflush_stringbuf</code>,
which is a slightly modified <code>basic_stringbuf</code>.
The modification is to note the flush rather than act upon it.
</p></li>

</ul>

<p>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3892.html">
N3892</a> revised
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3750.html">
N3750 C++ Ostream Buffers</a>
</p>

<ul>

<li><p>
Change name to <code>basic_ostream_buffer</code>
and add the usual typedefs.
</p></li>

<li><p>
Change interface to inherit from <code>basic_ostringstream</code>
rather than provide access to a member of that type.
</p></li>

<li><p>
Add a Revisions section.
</p></li>

</ul>


<h2><a name="References">References</a></h2>

<dl>

<dt><a name="PSL">[PSL]</a></dt>
<dd>
<cite>The Open Group Base Specifications Issue 6,
IEEE Std 1003.1, 2004 Edition</cite>,
functions, flockfile,
<a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/flockfile.html">
http://pubs.opengroup.org/onlinepubs/009695399/functions/flockfile.html</a>
</dd>

</dl>


</body></html>
