<!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;
}

dl.tldr {
  background-color: #F9F9F9;
  border: 1px solid #D1D1D1;
}
dt.question {
  color: #CC0000;
  font-weight: 900;
}
dd.answer {
  color: #008800;
}

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>DRAFT C++ Synchronized Buffered Ostream</title>
</head>
<body>
<h1>DRAFT C++ Synchronized Buffered Ostream</h1>

<p>
ISO/IEC JTC1 SC22 WG21 p0053r3 - 2016-11-12
</p>

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

<p>
<a href="#Introduction">Introduction</a><br>
<a href="#Solution">Solution</a><br>
<a href="#Design">Design</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#Feature">Feature Test</a><br>
<a href="#Wording">Wording</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#contents">17.6.1.2 Headers [headers]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#input.output.general">27.1 General [input.output.general]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#iostream.forward">27.3 Forward declarations [iostream.forward]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#syncstream">27.12 Synchronized output stream [syncstream]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#syncstream.overview">27.12.1 Overview [syncstream.overview]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#syncstream.osyncstream">27.12.2 Class template <code>basic_osyncstream</code> [syncstream.osyncstream]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#synstream.osyncstream.ctor">27.12.2.1 Constructor [syncstream.osyncstream.ctor]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#synstream.osyncstream.dtor">27.12.2.2 Destructor [synstream.osyncstream.dtor]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#synstream.osyncstream.assign">27.12.2.3 Assignment [synstream.osyncstream.assign]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#syncstream.osyncstream.mfun">27.12.2.4 Member Functions [syncstream.osyncstream.mfun]</a><br>
<a href="#implementation">Implementation</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,
some 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 mutexes, 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>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2013/n3750.html">N3750
C++ Ostream Buffers</a> proposed an explicit buffering,
at the direction of the general consensus
in the July 2013 meeting of the Concurrency Study Group.
In November 2014 a further updated version
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4187.html">N4187</a>
was discussed in Library Evolution in Urbana
and it was consensus to work with a library expert
to get the naming and wording better suited to LWG expectations.
Nico Josuttis volunteered to help the original authors.
More information on the discussion is available at
<a href="http://wiki.edg.com/twiki/bin/view/Wg21urbana-champaign/N4187">LEWG
wiki</a>
and the corresponding
<a href="https://issues.isocpp.org/show_bug.cgi?id=20">LEWG
bug tracker entry (20)</a>.
This paper address issues raised with
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4187.html">N4187</a>.
This paper has a change of title to reflect a change in class name,
but contains the same fundamental approach.
</p>


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

<p>
We propose a <code>basic_osyncstream</code>,
that buffers output operations for a wrapped stream.
The <code>basic_osyncstream</code>
will atomically transfer the contents
of an internal stream buffer
to a <code>basic_ostream</code>'s stream buffer
on destruction of the <code>basic_osyncstream</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_osyncstream</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>{
  osyncstream bout(cout);
  bout &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; '\n';
}</code></pre>


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

<p>
Here we list a set of objection to our proposal
in the form of questions.
We then give our reasons why other potential solutions
do not work as well as our proposed solution.
</p>

<dl class="tldr">

<dt class="question">
Why can I not just use <code>cout</code>?
It should be thread-safe.
</dt>
<dd class="answer"><p>
You will nott get data races for <code>cout</code>,
but that is not true for most other streams.
In addition there is no guarantee that
output from different threads appears in any sensible order.
Coherent output order is the main reason for this proposal.
</p></dd>

<dt class="question">
Why must osyncstream be an <code>ostream</code>?
Could a simple proxy wrapper work?
</dt>
<dd class="answer"><p>
To support all existing and user-defined output operators,
<code>osyncstream</code> must be an <code>ostream</code> subclass.
</p></dd>

<dt class="question">
Can you make a flush of the <code>osyncstream</code>
mean transfer the characters and flush the underlying stream?
</dt>
<dd class="answer"><p>
No, because the point of the <code>osyncstream</code>
is to collect text into an atomic unit.
Flushes are often emitted in calls where the body is not visible,
and hence unintentionally break up the text.
Furthermore, there may be more than one flush
within the lifetime of an <code>osyncstream</code>,
which would impose a performance loss
when an atomic unit of text needs only one flush.
The design decision is only to flush the underlying stream,
if the osyncstream was flushed,
and only once per atomic transfer of the character sequence.
</p></dd>

<dt class="question">
Can you flush just transfer the characters and not flush the underlying stream?
</dt>
<dd class="answer"><p>
The flush intends an effect on visible to the user.
So, we should preserve at least one flush.
The flush may not be visible to the code around the <code>osyncstream</code>,
and so its programmer cannot do a manual flush, because
attempting to flush the underlying stream that is shared among 
threads will introduce a data race.
</p></dd>

</dl>

<p>
While it has been pointed out that the implementation should actually reside in the used stream
buffer object, we believe the specification should hide that effect, because such a 
stream buffer is not intended to be ever be used standalone. Therefore, the specification
here only provides the basic_osyncstream class template and not any details on the 
underlying stream buffer implementing the mechanics. We have an implementation, where the 
basic_osyncstream is more or less just a shell to the real meat in the stream buffer
but that stream buffer is not meant to be exchanged or shared or anything.
</p>

<p>
We follow typical stream conventions
of <code>basic_</code> prefixes and typedefs.
</p>

<p>
The constructor for <code>osyncstream</code>
takes a non-const reference
to a <code>basic_ostream</code> obtaining its stream buffer
or a <code>basic_streambuf</code>.
This stream buffer indicates that
the destruction of the osyncstream
may write to the stream buffer obtained with the constructor argument.
</p>

<p>
The wording below
permits implementation of <code>basic_osyncstream</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>

<h3><a name="Feature">Feature Test</a></h3>

<p>
No header called <code>&lt;syncstream&gt;</code> exists;
testing for this header's existence is thus sufficient
for testing existence of the feature.
</p>

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

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

<h3><a name="contents">17.6.1.2 Headers [headers]</a></h3>
<p>Add a new entry to table 14 &mdash; C++ library headers :

<blockquote class=stdins>
<table>
<tr>
<td>&lt;syncstream&gt;</td>
</tr>
</table>
</blockquote>


<h3><a name="input.output.general">27.1 General [input.output.general]</a></h3>

<p>
Add a new row to table 129 &mdash; Input/output library summary.
</p>

<blockquote class=stdins>
<table>
<tr>
<td>27.12</td>
<td>Synchronized output streams</td>
<td>&lt;syncstream&gt;</td>
</tr>
</table>
</blockquote>

<h3><a name="iostream.forward">27.3 Forward declarations [iostream.forward]</a></h3>

<p>
Add the following forward declarations to the synopsis of &lt;iosfwd&gt;
in the <code>namespace std</code>.
</p>

<blockquote class="stdins">
<pre><code>template &lt;class charT,
          class traits = char_traits&lt;charT&gt;,
          class Allocator = allocator&lt;charT&gt; &gt;
  class basic_osyncstream;
typedef basic_osyncstream&lt;char&gt; osyncstream;
typedef basic_osyncstream&lt;wchar_t&gt; wosyncstream;
</code></pre>
</blockquote>


<h3><a name="syncstream">27.12 Synchronized output stream [syncstream]</a></h3>

<p>
Add a new section with the following subsections.
</p>


<h3><a name="syncstream.overview">27.12.1 Overview [syncstream.overview]</a></h3>

<blockquote class="stdins">
<p>
The header <code>&lt;syncstream&gt;</code>
provides a mechanism to synchronize execution agents writing to the same stream.
It defines a class template <code>basic_osyncstream</code>
to buffer output and
<!--atomically transfer the buffered content into a <code>basic_ostream</code> object.-->
transfer the buffered content into an object of type
<code>basic_streambuf&lt;charT,traits&gt;</code> atomically 
with respect to such transfers by other 
<code>basic_osyncstream&lt;charT,traits,Allocator&gt;</code> objects referring 
to the same <code>basic_streambuf&lt;charT,traits&gt;</code> object.
The transfer occurs when <code>emit()</code> is called
and when the <code>basic_osyncstream&lt;chart,traits,Allocator&gt;</code> 
object is destroyed.
</p>
</blockquote>

<p>
Add a synopsis for header <code>&lt;syncstream&gt;</code>.
</p>

<blockquote class="stdins">
<pre><code>template &lt;class charT,
          class traits,
          class Allocator&gt;
  class basic_osyncstream;
</code></pre>
</blockquote>


<h3><a name="syncstream.osyncstream">27.12.2 Class template <code>basic_osyncstream</code> [syncstream.osyncstream]</a></h3>

<blockquote class="stdins">
<pre><code>template &lt;class charT,
          class traits,
          class Allocator&gt;
class basic_osyncstream
  : public basic_ostream&lt;charT,traits&gt;
{
public:
  typedef charT                     char_type;
  typedef traits                    traits_type;
  typedef typename traits::int_type int_type;
  typedef typename traits::pos_type pos_type;
  typedef typename traits::off_type off_type;
  typedef Allocator                 allocator_type;
  typedef basic_streambuf&lt;charT,traits&gt; streambuf_type;

  explicit basic_osyncstream(streambuf_type *obuf,
                             Allocator const &amp;allocator = Allocator());
  explicit basic_osyncstream(basic_ostream&lt;charT,traits&gt; &amp;os,
                             Allocator const &amp;allocator = Allocator());
  basic_osyncstream(basic_osyncstream&amp;&amp;);
  ~basic_osyncstream();
  basic_osyncstream&amp; operator=(basic_osyncstream&amp;&amp;);
  void emit();
  streambuf_type* rdbuf_wrapped() const noexcept;
private:
  streambuf_type *out; // <i>exposition only</i>
};
</code></pre>

<p>
<code>Allocator</code> shall meet the allocator requirements [allocator.requirements]. 
</p>

<p>
[<i>Example:</i>
Use a named variable within a block statement for streaming
across multiple statements.
</p>
<pre class="example"><code>{
  osyncstream bout(cout);
  bout &lt;&lt; "Hello, ";
  bout &lt;&lt; "World!";
  bout &lt;&lt; endl; // flush is noted
  bout &lt;&lt; "and more!\n";
} // characters are transferred and cout is flushed
</code></pre>
<p>
&mdash;<i>end example</i>]
</p>

<p>
[<i>Example:</i>
Use a temporary object for streaming within a single statement. 
<code>cout</code> is not flushed.
</p>
<pre class="example"><code>osyncstream(cout) &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; '\n';</code></pre>
<p>
&mdash;<i>end example</i>]
</p>

</blockquote>


<h3><a name="synstream.osyncstream.ctor">27.12.2.1 Constructor [syncstream.osyncstream.ctor]</a></h3>

<blockquote class="stdins">

<dl>
<dt>
<code>explicit basic_osyncstream(streambuf_type *buf, Allocator const &amp;allocator = Allocator());</code>
</dt>
<dd>

<p><i>Effects:</i>
Stores the stream buffer pointer <code>buf</code>
which will be the final destination of characters in <code>out</code>. 
If 
the stored stream buffer pointer 
 <code>out == nullptr</code>
 output operations on 
<code>*this</code> fail.
A copy of <code>allocator</code> is used to allocate memory 
for the stream's own internal buffer, if any.
</p>

<p>
Constructs a stream buffer object [stream.buffers].
</p>
<p>
[<i>Note:</i>
If wrapped stream buffer pointer refers to a user provided stream buffer 
then its implementation must
be aware that its member functions might be called from <code>emit()</code> 
while a lock is held.
&mdash;<i>end note</i>]
</p>

<p><i>Postconditions:</i>
<code>out == buf</code>
</p>

<dt>
<code>explicit basic_osyncstream(basic_ostream&lt;charT,traits&gt;&amp; os, Allocator const &amp;allocator=Allocator());</code>
</dt>
<dd>
<p><i>Effects:</i>
<code>basic_osyncstream(os.rdbuf(),a)</code>
</dd>

<dt>
<code>basic_osyncstream(basic_osyncstream&amp;&amp; os);</code>
</dt>
<dd>

<p><i>Effects:</i>
First, the state necessary to perform <code>os.emit()</code> is moved to <code>*this</code>.
Then <code>os.out = nullptr</code>.
[<i>Note:</i>
This disassociates <code>os</code> from its wrapped stream buffer ensuring 
destruction of <code>os</code> produces no output.
&mdash;<i>end note</i>]
</p>
<p><i>Postconditions:</i>
The value returned by <code>this->rdbuf_wrapped()</code> is the value 
returned by <code>os.rdbuf_wrapped()</code> prior to calling this constructor. 
Output stored in <code>*os.rdbuf()</code> prior to calling this constructor
will be stored in <code>*this->rdbuf()</code> afterwards. 
Then <code>os.rdbuf()->pbase() == os.rdbuf()->pptr()</code>
 and
<code>nullptr == os.rdbuf_wrapped()</code>.
</p>

</dd>

</dl>

</blockquote>


<h3><a name="synstream.osyncstream.dtor">27.12.2.2 Destructor [synstream.osyncstream.dtor]</a></h3>

<blockquote class="stdins">

<dl>

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

<p><i>Effects:</i>
Calls <code>emit()</code>.
</p>

</dd>
</dl>

</blockquote>
<h3><a name="synstream.osyncstream.assign">27.12.2.3 Assignment [synstream.osyncstream.assign]</a></h3>

<blockquote class="stdins">

<dl>

<dt>
<code>basic_osyncstream& operator=(basic_osyncstream&amp;&amp; os);</code>
</dt>
<dd>

<p><i>Effects:</i>
First, calls <code>this-&gt;emit()</code>. 
Then the state necessary to perform <code>os.emit()</code> is moved to <code>*this</code>.
Then <code>os.out&nbsp;=&nbsp;nullptr</code>.
[<i>Note:</i>
This disassociates <code>os</code> from its wrapped stream buffer ensuring 
destruction of <code>os</code> produces no output.
&mdash;<i>end note</i>]</p>

<p><i>Postcondition:</i>
Primarily, <code>nullptr == os.rdbuf_wrapped()</code>. 

Also, <code>rdbuf_wrapped()</code> returns the value previously returned by 
<code>os.rdbuf_wrapped()</code>.
</p>

</dd>
</dl>

</blockquote>



<h3><a name="syncstream.osyncstream.mfun">27.12.2.4 Member Functions [syncstream.osyncstream.mfun]</a></h3>

<blockquote class="stdins">

<dl>

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

<p><i>Effects:</i>
Transfers the contents of the internal stream buffer
to the stream buffer <code>*out</code>,
so that they appear in the output stream as a contiguous sequence of characters.
If and only if a flush was requested on <code>*this</code>,&nbsp; 
<code>out->pubsync()</code> is called on the stream buffer obtained in the constructor. 
A failure in transferring the characters or flushing calls, such as <code>out</code>
having the value <code>nullptr</code>, result in <code>setstate(ios::badbit)</code>.
</p>

[<i>Note:</i>
A flush on a <code>basic_osyncstream</code>
does not flush the <code>basic_osyncstream</code> to the stream buffer,
but rather flushes the stream buffer
after transfering the contents of the <code>basic_osyncstream</code>
to the stream buffer.
[<i>Example:</i>
<pre class="example"><code>{
  osyncstream bout(cout);
  bout &lt;&lt; "Hello," &lt;&lt; '\n'; // no flush
  bout.emit(); // characters transferred; cout <em>not</em> flushed
  bout &lt;&lt; "World!" &lt;&lt; endl; // flush noted; bout <em>not</em> flushed
  bout.emit(); // characters transferred; cout <em>flushed</em>
  bout &lt;&lt; "Greetings." &lt;&lt; '\n'; // no flush
} // characters transferred; cout <em>not</em> flushed</code>
</pre>
<p>
&mdash;<i>end example</i>]
&mdash;<i>end note</i>]
</p>

<p><i>Synchronization:</i>
All <code>emit()</code> calls transferring characters 
to the same 
stream buffer object
appear to execute in a total order consistent with <i>happens-before</i> 
where each <code>emit()</code> call <i>synchronizes-with</i> subsequent 
<code>emit()</code> calls in that total order.
</p>
<p><i>Remarks:</i>
May hold a lock uniquely associated with the underlying 
stream buffer object obtained in the constructor while transferring characters.
</p>
<p>
[<i>Example:</i>
The function <code>emit()</code> can be used to catch exceptions 
from operations on the underlying stream.
</p>
<pre class="example"><code>{
  osyncstream bout(cout);
  bout &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; '\n';
  try {
    bout.emit();
  } catch ( ... ) {
    // stuff
  }
}</code>
</pre>
<p>
&mdash;<i>end example</i>]
</p>

</dd>

<dt><code>streambuf_type* rdbuf_wrapped() const noexcept;</code></dt>
<dd>

<p><i>Returns:</i>
<code>out</code>
</p>

<p>[<i>Example:</i>
Obtaining the wrapped stream buffer with <code>rdbuf_wrapped()</code> 
allows wrapping it again with an <code>osyncstream</code>.
For example,
</p>
<pre class="example"><code>{
  osyncstream bout1(cout);
  bout1 &lt;&lt; "Hello, ";
  {
    osyncstream bout2(bout1.rdbuf_wrapped());
    bout2 &lt;&lt; "Goodbye, " &lt;&lt; "Planet!" &lt;&lt; '\n';
  }
  bout1 &lt;&lt; "World!" &lt;&lt; '\n';
}</code></pre>
<p>
produces the <em>uninterleaved</em> output
</p>
<pre class="example"><code>Goodbye, Planet!
Hello, World!
</code></pre>
<p>
&mdash;<i>end example.</i>]
</p>


</dd>


</dl>

</blockquote>

<h2><a name="implementation">Implementation</a></h2>

<p>
Two example implementations are available on 
<a href="https://github.com/PeterSommerlad/SC22WG21_Papers/tree/master/workspace/Test_basic_osyncstream">
github.com/PeterSommerlad/SC22WG21_Papers/workspace/Test_basic_osyncstream</a> and
<a href="https://github.com/PeterSommerlad/SC22WG21_Papers/tree/master/workspace/p0053_basic_osyncstreambuf">
https://github.com/PeterSommerlad/SC22WG21_Papers/tree/master/workspace/p0053_basic_osyncstreambuf</a>.
</p>
<p>The latter actually implements almost all of the mechanics in a stream buffer
as proposed by Pablo Halpern where the first one is my original implementation with 
most of the mechanics stuck in the basic_osyncstream.
</p>


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

<p>
This paper revises
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0053r2.html">
P0053R2 C++ Synchronized Buffered Ostream</a>
</p>
<ul>

<li><p>
Remove the "may construct a mutex" notes.
</p></li>

<li><p>
Remove "may destroy mutex" notes.
</p></li>

<li><p>
Clarify osyncstream flush behavior in an example.
</p></li>

<li><p>
Make minor editorial fixes.
</p></li>

</ul>

<p>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0053r2.html">
P0053R2</a> revised
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0053r1.html">
P0053R1 C++ Synchronized Buffered Ostream</a>
</p>
<ul>
<li>
<p>
Provide a typedef for the wrapped stream buffer and use it to shorten the specification 
as suggested by Daniel Kr&uuml;gler.
</p>
</li>
<li>
<p>
Provide move construction and move assignment and specify the moved-from state to be 
detached from the wrapped stream buffer.
</p>
</li>
<li>
<p>
Rename <code>get()</code> to <code>rdbuf_wrapped()</code> and provide noexcept specification.
</p>
</li>
<li>
<p>
Changed to explicitly rely on wrapping a stream buffer, 
instead of an ostream object and adjust explanations accordingly.
</p>
</li>
</ul>

<p>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0053r1.html">
P0053R1</a> revised
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0053r0.html">
P0053R0 C++ Synchronized Buffered Ostream</a>
</p>
<ul>
<li>
<p>
Add remark to note that exchanging the stream buffer while the stream is wrapped causes
undefined behavior and added a note to warn stream buffer implementers about the lock 
being held in <code>emit()</code>. Call setstate(badbit) if IO errors occur in emit().
</p>
</li>
<li>
<p>
Replace code references to <code>basic_streambuf</code> by the 
term <i>stream buffer</i> introduced in [stream.buffers].
</p>
</li>
<li>
<p>
Provide an example implementation.
</p>
</li>
<li>
<p>
The lock is to be associate to the underlying <code>basic_streambuf</code> instead of the <code>basic_stream</code>.
</p>
</li>
<li>
<p>
Added an <code>Allocator</code> constructor parameter.
</p>
</li>
<li>
<p>
Moves destructor example to <code>emit()</code>.
</p>
</li>
<li>
<p>
Clarifies wording about synchronization and flushing (several times).
</p>
</li>
<li>
<p>
List the new header in corresponding table.
</p>
</li>
<li>
<p>
Provide type aliases in <code>&lt;iosfwd&gt;</code>.
</p>
</li>
<li>
<p>
Removed copy constructor in favor of providing <code>get()</code>.
</p>
</li>
<li>
<p>
Notify that move construction and assignment is deleted.
</p>
</li>
<li>
<p>
Moved class noteflush_streambuf into an implementation note.
</p>
</li>
<li>
<p>
Add a design subsection that states that
a header test is a sufficient feature test.
</p>
</li>
</ul>


<p>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0053r0.html">
P0053R0</a> revised
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/N4187.html">
N4187 C++ Ostream Buffers</a>
</p>

<ul>

<li><p>
Updated introduction with recent history.
</p></li>

<li><p>
Rename <code>ostream_buffer</code> to <code>osyncstream</code>
to reflect its appearance is more like a stream than like a buffer.
</p></li>

<li><p>
Add an example of using <code>osyncstream</code> as a temporary object.
</p></li>

<li><p>
Add an example of a <code>osyncstream</code>
constructed with another <code>osyncstream</code>.
</p></li>

<li><p>
Clarify the behavior of nested <code>osyncstream</code> executions.
</p></li>

<li><p>
Clarify the behavior of exceptions
occuring with the <code>osyncstream</code> destructor.
</p></li>

<li><p>
Clarify the deferral of flush from the 
<code>osyncstream</code>'s <code>streambuf</code>
to the final <code>basic_ostream</code>.
</p></li>

<li><p>
Limit the number of references to <code>noteflush_stringbuf</code>
in anticipation of the committee removing it from the specification.
</p></li>

<li><p>
Rename <code>noteflush_stringbuf</code>
to <code>noteflush_streambuf</code> to hide possible implementation details.
</p></li>

<li><p>
Change the base class of <code>noteflush_streambuf</code>
from <code>basic_stringbuf</code> to <code>basic_streambuf</code>.
</p></li>

</ul>

<p>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4187.html">
N4187</a>
revised
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4069.html">
N4069 C++ Ostream Buffers</a>
</p>

<ul>
<li><p>
Added note to sync as suggested by BSI via email.
</p></li>
</ul>

<p>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4069.html">
N4069</a>
revised
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3978.html">
N3978 C++ Ostream Buffers</a>
</p>

<ul>

<li><p>
Added a Design section.
</p></li>

<li><p>
Clarify the reference capturing behavior
of the <code>ostream_buffer</code> constructors.
</p></li>

<li><p>
Added noexcept and const as appropriate to members.
</p></li>

<li><p>
Added note on throwing wrapped streams.
</p></li>

<li><p>
Change the
<code>noteflush_stringbuf</code>
public member variable
<code>needsflush</code>
to a public member query function <code>flushed</code>.
</p></li>

<li><p>
Removed the public member function <code>noteflush_stringbuf::clear</code>.
</p></li>

<li><p>
Minor synopsis formatting changes.
</p></li>

<li><p>
Incorporated feedback from SG1 and Dietmar K&uuml;hl in specific in Rapperswil.
</p></li>
</ul>

<p>
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n3978.html">
N3978</a> revised
<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>
