<!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 P0053 - 2015-09-23
</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>
<a href="#Wording">Wording</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="#sync.stream">27.10 Synchronized Output Stream [sync.stream]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sync.stream.overview">27.10.1 Overview [sync.stream]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sync.stream.osyncstream">27.10.2 Class template <code>basic_osyncstream</code> [sync.stream.osyncstream]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sync.stream.osyncstream.ctor">27.10.2.1 Constructor [sync.stream.osyncstream.ctor]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sync.stream.osyncstream.dtor">27.10.2.2 Destructor [sync.stream.osyncstream.dtor]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sync.stream.osyncstream.mfun">27.10.2.3 Member Functions [sync.stream.osyncstream.mfun]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sync.stream.streambuf">27.10.3 Class template <code>noteflush_streambuf</code> [sync.stream.streambuf]</a><br>
&nbsp;&nbsp;&nbsp;&nbsp;<a href="#sync.stream.streambuf.mfun">27.10.3.1 Member Functions [sync.stream.streambuf.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>
<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 an <code>ostream</code>
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>{
  std::osyncstream bout(std::cout);
  bout &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; std::endl;
}</code>
....
</pre>


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

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

<p>
The constructors for <code>osyncstream</code>
take non-const references
to either a <code>basic_ostream</code>
or a <code>basic_osyncstream</code>.
This non-const reference indicates that
the destruction of the buffer
may write to the stream associated with the argument.
</p>

<p>
The constructors for <code>osyncstream</code>
from another <code>osyncstream</code>
is not a copy constructor,
but an attachment to the argument buffer.
This approach enables nested
passing an <code>osyncstream</code>
to a function expecting an <code>ostream</code>,
which then in turn uses an <code>osyncstream</code>
on that <code>ostream</code>
</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>


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

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


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

<p>
Add a new row to table 120.
</p>

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


<h3><a name="sync.stream">27.10 Synchronized Output Stream [sync.stream]</a></h3>

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


<h3><a name="sync.stream.overview">27.10.1 Overview [sync.stream]</a></h3>

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

<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
indivisibly transfer the buffered content into an <code>ostream</code>.
The transfer occurs either
on destruction or
by explicit request by calling <code>emit()</code>.
</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 = 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;

template &lt;class charT,
          class traits = char_traits&lt;charT&gt;,
          class Allocator = allocator&lt;charT&gt; &gt;
  class noteflush_streambuf;
</code></pre>
</blockquote>


<h3><a name="sync.stream.osyncstream">27.10.2 Class template <code>basic_osyncstream</code> [sync.stream.osyncstream]</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_osyncstream
  : public std::basic_ostream&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;

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

<p>
The class template <code>basic_osyncstream</code>
supports buffering into an internal buffer
and then
indivisibly transfering the contents of the buffer
to a <code>basic_ostream</code>.
</p>

<p>
[<i>Example:</i>
Use a named variable within a block statement for streaming
acrosss multiple statments.
</p>
<pre class="example">....
<code>{
  std::osyncstream bout(std::cout);
  bout &lt;&lt; "Hello, ";
  bout &lt;&lt; "World!";
  bout &lt;&lt; std::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>std::osyncstream(std::cout) &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; std::endl;</code>
....
</pre>
<p>
&mdash;<i>end example</i>]
</p>

</blockquote>


<h3><a name="sync.stream.osyncstream.ctor">27.10.2.1 Constructor [sync.stream.osyncstream.ctor]</a></h3>

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

<blockquote class="stdins">

<dl>

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

<p><i>Effects:</i>
Stores a reference to the <code>basic_ostream</code>,
which will be the final destination of characters.
</p>

<p>
May construct a mutex.
</p>

<p>
Constructs a <code>streambuf</code>.
Any flush on the <code>streambuf</code>
will not act immediately on the <code>basic_ostream</code>,
but will be deferred until immediately after
the transfer of characters to the <code>basic_ostream</code>.
</p>

</dd>

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

<p><i>Effects:</i>
Stores a reference to the <code>basic_ostream</code>
referenced by <code>osb</code>,
which will be the final destination of characters.
</p>

<p>
May construct a mutex.
</p>

<p>
Constructs a <code>streambuf</code>.
Any flush on the <code>streambuf</code>
will not act immediately on the <code>basic_ostream</code>,
but will be deferred until immediately after
the transfer of characters to the <code>basic_ostream</code>.
</p>

<p>[<i>Example:</i>
This overload exists to allow wrapping a <code>basic_osyncstream</code>
again with a <code>basic_osyncstream</code>.
For example,
</p>
<pre class="example">....
<code>{
  std::osyncstream bout1(std::cout);
  bout1 &lt;&lt; "Hello, ";
  {
    std::osyncstream bout2(bout1);
    bout2 &lt;&lt; "Goodbye, " &lt;&lt; "Planet!" &lt;&lt; std::endl;
  }
  bout1 &lt;&lt; "World!" &lt;&lt; std::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>


<h3><a name="sync.stream.osyncstream.dtor">27.10.2.2 Destructor [sync.stream.osyncstream.dtor]</a></h3>

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

<blockquote class="stdins">

<dl>

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

<p><i>Effects:</i>
as if <code>emit()</code>.
May destroy a lock.
</p>

<p>
If the underlying stream throws an exception,
the exception is ignored and any output is unspecified.
If any underlying mutex lock throws an exception,
the exception is ignored and no output occurs.
it is returned to the environment, as in <code>lock_guard</code>.
If any underlying mutex unlock throws an exception,
the exception is ignored and any output is unspecified.
[<i>Note:</i>
An exception in mutex unlock is not permitted
for standard-conformant mutexes.
See 30.4.1.2 Mutex types [thread.mutex.requirements.mutex].
&mdash;<i>end note</i>]
</p>


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

<p>
[<i>Example:</i>
To protect against exceptions from within the destructor,
use <code>emit()</code> to catch them.
</p>
<pre class="example"><code>{
  std::osyncstream bout(std::cout);
  bout &lt;&lt; "Hello, " &lt;&lt; "World!" &lt;&lt; std::endl;
  try {
    bout.emit();
  }
  catch ( ... ) {
    ....
  }
}</code>
</pre>
<p>
&mdash;<i>end example</i>]
</p>

</dd>
</dl>

</blockquote>


<h3><a name="sync.stream.osyncstream.mfun">27.10.2.3 Member Functions [sync.stream.osyncstream.mfun]</a></h3>

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

<blockquote class="stdins">

<dl>

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

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

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

</dd>
</dl>

</blockquote>


<h3><a name="sync.stream.streambuf">27.10.3 Class template <code>noteflush_streambuf</code> [sync.stream.streambuf]</a></h3>

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

<blockquote class="stdins">

<pre><code>template &lt;class charT, class traits, class Allocator&gt;
class noteflush_streambuf
  : public std::basic_streambuf&lt;charT,traits,Allocator&gt;
{
  protected:
    virtual int sync();
};
</code></pre>
<p>
The class template <code>noteflush_streambuf</code>
behaves like a <code>basic_stringbuf</code>
except that flushes of the stream using it,
which incur in calling the <code>sync()</code> member function,
are noted instead of being a no-op.
</p>

</blockquote>


<h3><a name="sync.stream.streambuf.mfun">27.10.3.1 Member Functions [sync.stream.streambuf.mfun]</a></h3>

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

<blockquote class="stdins">

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

<p><i>Effects:</i>
Notes the request of a flush within the object.
</p>
<p>[<i>Note</i>:
Any call to <code>sync()</code> ensures that
a subsequent call to <code>emit()</code>
in the owning <code>basic_osyncstream</code>
will flush the stream being synchronized.
&mdash;<i>end note</i>]
</p>

<p><i>Returns:</i>
<code>0</code>.
</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/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>

