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

<p>
ISO/IEC JTC1 SC22 WG21 p0053r2 - 2016-07-05
</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 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>
<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; endl;
}</code></pre>


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

<p>
While it has been pointed out that the implementation should actually in the used stream
buffer object, I believe the specification should hide that effect, because such a 
stream buffer is not intended to be ever be used stand alone. Therefore, the specification
here only provides the basic_osyncstream class template and not any details on the 
underlying stream buffer implementing the mechanics. I 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>
The class template <code>basic_osyncstream</code>
supports buffering into an internal buffer
and then
transferring the contents of the buffer
to a <code>basic_ostream</code> atomically with respect to other 
<code>basic_osyncstream</code> objects referring to the same <code>basic_ostream</code>.
</p>-->

<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;
}</code></pre>
<p>
&mdash;<i>end example</i>]
</p>

<p>
[<i>Example:</i>
Use a temporary object for streaming within a single statement.
</p>
<pre class="example"><code>osyncstream(cout) &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; endl;</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 streams own internal buffer, if any.
</p>

<p>
Constructs a stream buffer object [stream.buffers].
<!--of a type derived from <code>basic_streambuf&lt;charT,traits&gt;</code>.
Any flush on the created <code>basic_osyncstream</code> 
meaning internally calling <code>sync()</code> 
on the constructed stream buffer object will not act immediately on <code>os</code>,
but will be deferred until immediately after
the transfer of characters to <code>os</code> in <code>emit()</code>.-->
</p>
<p>
[<i>Note:</i>
May construct a mutex. 
&mdash;<i>end note</i>]
</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>
The state necessary to perform <code>os.emit()</code> is moved to <code>*this</code>.
<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. 
<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>

<p>
[<i>Note:</i> 
May destroy a mutex. 
&mdash;<i>end note</i>]
</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>
Calls <code>emit()</code>. 
The state necessary to perform <code>os.emit()</code> is moved to <code>*this</code>.
<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>Postcondition:</i>
<code>nullptr == os.rdbuf_wrapped()</code>. 

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

<p>
[<i>Note:</i> 
May destroy a mutex. 
&mdash;<i>end note</i>]
</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>

<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; endl;
  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; endl;
  }
  bout1 &lt;&lt; "World!" &lt;&lt; endl;
}</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/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>
This paper revises
<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>
This paper revises
<a href="http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/P0053R0.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>
