<html>
<head>
<title>N2888: Moving Futures - Proposed Wording for UK comments 335, 336,
  337 and 338</title>

<style type="text/css">
.inserted
{
    color: black;
    background: #a0ffa0;
}
.deleted
{
    color: black;
    background: #ffa0a0;
    text-decoration: line-through;
}
.standardtext
{
    margin-left: 2em;
}
</style>

</head>
<body>
<table>
<tr><td>Document Number:</td><td>09-0078=N2888</td></tr>
<tr><td>Date:</td><td>2009-06-18</td></tr>
<tr><td>Author:</td><td><a href="mailto:anthony@justsoftwaresolutions.co.uk">Anthony
      Williams</a><br>Just Software Solutions Ltd</td></tr>
</table>

<h1>N2888: Moving Futures - Proposed Wording for UK comments 335, 336,
  337 and 338</h1>

<p>UK comments 335 (which is
  also <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1048">LWG
  issue 1048<a>), 336, 337 and 338 in the CD1 ballot propose changes
  to the working draft to support working
  with <code>std::unique_future&lt&gt;</code>
  and <code>std::shared_future&lt;&gt;</code>. This paper provides
  additional rationale for the suggested changes, along with proposed
  wording based on N2857.</p>

<h2>Moving <code>std::unique_future&lt;&gt;</code></h2>

<p>In the current working draft (N2857),
  <code>std::unique_future&lt;&gt;</code>
  is <code>MoveConstructible</code> but
  not <code>MoveAssignable</code>. This is a strange state of affairs
  that leads to bizarre consequences. For example, you can
  move <em>from</em> an instance
  of <code>std::unique_future&lt;&gt;</code>, leaving an empty shell,
  but not move <em>into</em> an instance to provide meaningful
  operations. e.g.</p>

<pre>
std::unique_future&lt;int&gt; make_future();

void foo()
{
    std::unique_future&lt;int&gt; f1(make_future());
    std::unique_future&lt;int&gt; f2(std::move(f1)); // OK, f1 now useless
    f1=make_future(); // Error, no move-assignment operator
}
</pre>

<h3>Containers of <code>std::unique_future&lt;&gt;</code></h3>

<p>The fact that <code>std::unique_future&lt;&gt;</code>
  is <code>MoveConstructible</code> means that you can store instances
  in a container such as <code>std::vector&lt;&gt;</code>, but this
  container is severely limited. For example, you can
  call <code>push_back</code> on
  a <code>std::vector&lt;std::unique_future&lt;int&gt;&gt;</code>, but
  not <code>insert</code>, and you can delete elements from the end by
  using <code>pop_back</code>, but not by
  calling <code>erase</code>.</p>

<pre>
void bar()
{
    std::vector&lt;unique_future&lt;int&gt;&gt; vec;
    vec.push_back(make_future());        // OK
    vec.insert(vec.end(),make_future()); // error, requires MoveAssignable
    vec.pop_back();                      // OK
    vec.erase(vec.begin());              // error, requires MoveAssignable
}
</pre>

<p>Use of futures with standard containers is an important feature. An
  algorithm written to make use of multiple threads might well divide
  its work into multiple sub-tasks, and store
  a <code>std::unique_future&lt;&gt;</code> for each in some form of
  container. Making it easy to manipulate this container is very
  important for this primary use case.</p>

<p>As an aside, it is worth noting that
  since <code>std::unique_future&lt;&gt;</code>
  is <code>MoveConstructible</code>, you can <em>emulate</em>
  move-assignment with destruction and move-construction:</p>

<pre>
template&lt;typename T&gt;
void move_assign(std::unique_future&lt;T&gt; &amp; target,
                 std::unique_future&lt;T&gt; &amp;&amp; source)
{
    target.&tilde;std::unique_future&lt;T&gt;();
    new (&amp;target) std::unique_future&lt;T&gt;(std::move(source));
}
</pre>

<p>You can even write a <code>concept_map</code> that does this for
  particular instantiations
  of <code>std::unique_future&lt;UserDefinedType&gt;</code>, though
  the standard prohibits you from doing this for instantiations that
  don't involve a user-defined type:

<pre>
struct MyType{};

concept_map std::MoveAssignable&lt;std::unique_future&lt;MyType&gt;&gt;
{
    std::unique_future&lt;MyType&gt;&amp; operator=(
        std::unique_future&lt;MyType&gt;&amp;&amp; rhs)
    {
        this-&gt;&tilde;std::unique_future&lt;MyType&gt;();
        new (this) std::unique_future&lt;MyType&gt;(std::move(rhs));
        return *this;
    }
}
</pre>

<p>Such a concept map would allow you to use move-assignment
  seamlessly in constrained templates such
  as <code>std::vector&lt;&gt;</code>, but <em>only for instantiations
  involving a user-defined type</em>.</p>

<p>Given that you can write such code, it seems most unfortunate that
  you cannot just write a direct move-assignment in unconstrained code:

<pre>
    target=std::move(source);
</pre>

<p>For the reasons presented above, UK comment 336 proposes that a
  move-assignment operator is added
  to <code>std::unique_future&lt;&gt;</code>. </p>

<h2>Default construction of <code>std::unique_future&lt;&gt;</code></h2>

<p>Even with a move-assignment
  operator, <code>std::unique_future&lt;&gt;</code> is still severely
  limited, since it lacks a default constructor so you must construct
  it with a value. This prevents calling <code>resize</code> on
  a <code>std::vector&lt;std::unique_future&lt;&gt;&gt;</code>, and
  again limits the use of <code>std::unique_future&lt;&gt;</code> for
  holding the results of sub-tasks &mdash; it can be beneficial to be
  able to allocate the container to hold the results prior to actually
  starting the tasks and obtaining the correct futures. Preventing
  default construction makes this unnecessarily difficult. It also
  means that arrays can only be created if every element is
  initialized, which is not always readily possible.</p>

<p>For example, if your algorithm can be divided into a number of
  predefined steps, it may make sense to create an array of futures to
  hold the results of the subtasks in order to avoid the overhead of
  additional dynamic memory allocation. This is made considerably
  easier if the futures support default construction, since the
  already-constructed futures can be waited-for if subsequent tasks
  cannot be started for some reason, rather than just being
  destroyed. For example:

<pre>
class task_data{};
class result_type{};

unsigned const num_steps=42;
std::unique_future&lt;result_type&gt; run_subtask(task_data&amp; state,unsigned step);

void parallel_task()
{
    task_data state;
    std::unique_future&lt;result_type&gt; results[num_steps];
    unsigned count=0;
    try
    {
        for(count=0;count&lt;num_steps;++count)
        {
            results[count]=run_subtask(state,count);
        }
    }
    catch(...)
    {
        state.set_cancel_flag();
        for(unsigned i=count;i!=0;)
        {
            --i;
            results[i].wait();
        }
        throw;
    }
}
</pre>

<p>Such a construction becomes more difficult
  if <code>std::unique_future&lt;&gt;</code> doesn't support default
  construction.</p>

<p>At first glance, omitting default construction prevents the
  construction of <code>std::unique_future&lt;&gt;</code> values
  without an associated state. However, this is not the case: such an
  instance can be obtained by using an object as the source of a
  move-construction:

<pre>
void foo()
{
    std::unique_future&lt;int&gt; f1(make_future());
    std::unique_future&lt;int&gt; f2(std::move(f1));
    // f1 is now "empty", just like a default-constructed instance would be
}
</pre>

<p>Therefore UK comment 336 also proposes to allow default
  construction of <code>std::unique_future&lt;&gt;</code>.

<h2>Move-assignment for <code>std::shared_future&lt;&gt;</code></h2>

<p><code>std::shared_future&lt;&gt;</code> is
  currently <code>CopyConstructible</code>, but
  not <code>CopyAssignable</code> or <code>MoveAssignable</code>. As
  for <code>std::unique_future&lt;&gt;</code>, this can lead to
  bizarre restrictions on the use of the type with containers such
  as <code>std::vector&lt;&gt;</code>.</p>

<p>The key benefit to be obtained from the lack of assignment is that
  instances are immutable. However, declaring individual
  instances <code>const</code> provides this property in a way much
  more consistent with the rest of the language.</p>

<p>As for <code>std::unique_future&lt;&gt;</code>, it therefore makes
  sense to
  make <code>std::shared_future&lt;&gt;</code> <code>MoveAssignable</code>
  too.</p>

<p>Since <code>std::shared_future&lt;&gt;</code>
is <code>CopyConstructible</code>, many of the use cases for making
it <code>MoveAssignable</code> can be addressed by making
  it <code>CopyAssignable</code> instead. However, the UK position is
  that move-assignment is still beneficial. See the section
  on <a href="#move_construct_shared_future">move-construction
    for <code>std::shared_future&lt;&gt;</code></a> below for further
  rationale on that point.</p>

<p>Incidentally, disallowing move-assignment does not prevent the
  existence of <code>std::shared_future&lt;&gt;</code> instances with
  no associated state, since you could construct such an instance by
  move-construction from an
  already-moved-from <code>std::unique_future&lt;&gt;</code> instance:

<pre>
    std::unique_future&lt;int&gt; uf1=make_future();
    std::unique_future&lt;int&gt; uf2(std::move(uf1));
    std::shared_future&lt;int&gt; sf1(std::move(uf1));
</pre>

<p>UK comment 338 therefore proposes
  that <code>std::shared_future&lt;&gt;</code> be
  made <code>MoveAssignable</code> by the addition of a
  move-assignment operator.</p>

<h2>Copy-assignment for <code>std::shared_future&lt;&gt;</code></h2>

<p>Given a <code>CopyConstructible</code>
  and <code>MoveAssignable</code> type, it is possible to perform
  copy-assignment by move-assignment from a copy of the original:</p>

<pre>
    std::shared_future&lt;int&gt; sf1=make_shared_future();
    std::shared_future&lt;int&gt; sf2=make_another_shared_future();

    sf2=std::shared_future&lt;int&gt;(sf1); // move-assign from a copy
</pre> 

<p>If the desirability of move-assignment
  for <code>std::shared_future&lt;&gt;</code> is accepted, it
  therefore seems a natural extension to allow copy assignment.</p>

<p>UK comment 338 therefore proposes
  that <code>std::shared_future&lt;&gt;</code> be
  made <code>CopyAssignable</code> by the addition of a
  copy-assignment operator.</p>

<h2><a name="move_construct_shared_future">Move-construction for <code>std::shared_future&lt;&gt;</code></a></h2>

<p>By its very nature, multiple instances
  of <code>std::shared_future&lt;&gt;</code> can refer to the same
  associated state. This means that in order for the state to be
  correctly destroyed when the last future that references it is
  destroyed some kind of reference counting scheme must be
  used. If <code>std::shared_future&lt;&gt;</code> only has a copy
  constructor and not a move constructor then this count must be
  updated even if the source is a temporary that is about to be
  destroyed. In this case, if the copy cannot be elided then the count
  must be incremented during the construction of the copy and then
  decremented during the destruction of the temporary. Atomic
  operations are expensive, so this is an unnecessary performance
  drain.</p>

<p>The same problem existed for <code>std::shared_ptr&lt;&gt;</code>,
  and for this reason <code>std::shared_ptr&lt;&gt;</code> has a
  move constructor and move-assignment operator in addition to the
  copy constructor and copy-assignment operator. This was introduced
  in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm#move">N2351:
  Improving shared_ptr for C++0x, revision 2</a>.</p>

<p>Though it could be argued that this is a Quality-of-Implementation
  issue, the consequences of not allowing move semantics
  for <code>std::shared_future&lt;&gt;</code> can be a noticeable
  performance impact, particularly with containers of such
  objects. Also, not only does such unnecessary incrementing and
  decrementing of the counter affect the performance of the current
  thread, it can also affect the performance of other threads which
  are accessing <code>std::shared_future&lt;&gt;</code> instances that
  reference the same associated state, due to cache line contention.</p>

<p>As an important optimization, and for consistency
  with <code>std::shared_ptr&lt;&gt;</code>, UK comments 337 and 338
  therefore propose that <code>std::shared_future&lt;&gt;</code>
  should have a move constructor and move-assignment operator.</p>

<h2>Detecting futures without an associated value</h2>

<p>If you move from a <code>std::unique_future&lt;&gt;</code>
  or <code>std::shared_future&lt;&gt;</code> then the source object
  has no associated value. This means that calling
  the <code>wait</code> or <code>get</code> member functions is not
  permitted. If the proposal to allow default construction of futures
  is accepted, then the same problem will exist for such
  default-constructed futures.</p>

<p>This allows for better handling of containers of futures where
  individual elements may or may not have associated state, as you can
  erase or reuse elements that have no associated state, or avoid
  waiting for such elements.</p>

<p>UK comment 335 proposes to address this by the provision of a new
  member function <code>waitable</code> which can always be safely
  called on an instance of a future. If a call
  to <code>waitable</code> on a given object
  returns <code>false</code> then the object has no associated value,
  so calling <code>wait</code> or <code>get</code> will throw. On the
  other hand, if a call to <code>waitable</code>
  returns <code>true</code> then the object <em>does</em> have an
  associated value, so calls to <code>wait</code> and <code>get</code>
  should
  succeed. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#1048">LWG
  issue 1048<a> has been opened from this comment, but currently lacks
  proposed wording.</p>

<h2>Proposed Wording</h2>

<p>These wording changes are based on the current working paper,
  N2857. <span class="inserted">Additions</span>
  and <span class="deleted">deletions</span> are marked in green and
  red as shown here.</p>

<h3>Changes to 30.6.4 [futures.unique_future]</h3>
<p>Update the class synopsis
  of <code>std::unique_future</code> as follows:</p>

<pre class="standardtext">
template&lt;class R&gt;
class unique_future {
public:
    <span class="inserted">unique_future();</span>
    unique_future(const unique_future&amp; rhs) = delete;
    <span class="inserted">unique_future(unique_future&amp;&amp; rhs);</span>
    &tilde;unique_future();
    unique_future &amp; operator=(const unique_future&amp; rhs) = delete;
    <span class="inserted">unique_future&amp; operator=(unique_future&amp;&amp; rhs);</span>

    <span class="inserted">bool waitable() const;</span>
    // retrieving the value
    see below get() const;

    // functions to check state and wait for ready
    bool is_ready() const;
    bool has_exception() const;
    bool has_value() const;

    void wait() const;
    template &lt;class Rep, class Period&gt;
    bool wait_for(const chrono::duration&lt;Rep, Period&gt;&amp; rel_time) const;
    template &lt;class Clock, class Duration&gt;
    bool wait_until(const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time) const;
};
</pre>

<p>Add the following after current paragraph 1:</p>

<pre class="standardtext inserted">
unique_future();
</pre>

<dl class="standardtext inserted">
<dt>Effects:</dt>
<dd>Construct a new instance of <code>unique_future</code> with no
  associated state.</dd>
<dt>Postcondition:</dt>
<dd><code>waitable()</code> returns <code>false</code></dd>
</dl>

<p>Modify the current paragraph 3 (postcondition of move-constructor)
as follows:</p>

<dl class="standardtext">
  <dt>Postcondition:</dt>
  <dd><span class="deleted"><code>rhs</code> can be safely
  destroyed.</span> <span class="inserted">Calling <code>waitable</code>
  on the newly-constructed object returns the same value
  as <code>rhs.waitable()</code> prior to the constructor
  invocation. <code>rhs.waitable()</code>
  returns <code>false</code>.</span></dd>
</dl>

<p>Add the following after the current paragraph 4:</p>

<pre class="standardtext inserted">
unique_future&amp; operator=(unique_future&amp;&amp; rhs);
</pre>

<dl class="standardtext inserted">
<dt>Effects:</dt>
<dd>Transfer the state associated with <code>rhs</code>
  to <code>this</code>. If <code>this-&gt;waitable()</code>
  was <code>true</code> prior to the assignment, and there are
  no <code>promise</code> or <code>packaged_task</code> instances
  referencing that state, then destroy that state.</dd>
<dt>Postcondition:</dt>
<dd>Calling <code>waitable</code> on the newly-constructed object
  returns the same value as <code>rhs.waitable()</code> prior to the
  assignment invocation. <code>rhs.waitable()</code>
  returns <code>false</code>.</dd>
</dl>

<pre class="standardtext inserted">
bool waitable() const;
</pre>

<dl class="standardtext inserted">
<dt>Returns:</dt>
<dd><code>true</code> if <code>this</code> has associated
  state, <code>false</code> otherwise.</dd>
</dl>

<p>Add a new paragraph following the current paragraph 5 as part of
  the description of <code>unique_future::get()</code>:</p>

<dl class="standardtext inserted">
<dt>Precondition:</dt>
<dd><code>waitable()</code>
  returns <code>true</code>.</dd>
</dl>

<p>Add a new paragraph prior to the current paragraph 13 as part of
  the description of <code>unique_future::wait()</code>:</p>

<dl class="standardtext inserted">
<dt>Precondition:</dt>
<dd><code>waitable()</code>
  returns <code>true</code>.</dd>
</dl>

<p>Add a new paragraph prior to the current paragraph 16 as part of
  the description of <code>unique_future::wait_for()</code>:</p>

<dl class="standardtext inserted">
<dt>Precondition:</dt>
<dd><code>waitable()</code>
  returns <code>true</code>.</dd>
</dl>

<p>Add a new paragraph prior to the current paragraph 19 as part of
  the description of <code>unique_future::wait_until()</code>:</p>

<dl class="standardtext inserted">
<dt>Precondition:</dt>
<dd><code>waitable()</code>
  returns <code>true</code>.</dd>
</dl>

<h3>Changes to 30.6.5 [futures.shared_future]</h3>
<p>Alter the class synopsis
  of <code>std::shared_future</code> as follows:</p>

<pre class="standardtext">
template&lt;class R&gt;
class shared_future {
public:
    <span class="inserted">shared_future();</span>
    shared_future(const shared_future&amp; rhs);
    <span class="inserted">shared_future(shared_future&amp;&amp; rhs);</span>
    shared_future(unique_future&lt;R&gt;);
    &tilde;shared_future();
    shared_future &amp; operator=(const shared_future&amp; rhs)<span class="deleted"> = delete</span>;
    <span class="inserted">shared_future&amp; operator=(shared_future&amp;&amp; rhs);</span>

    <span class="inserted">bool waitable() const;</span>
    // retrieving the value
    see below get() const;
    // functions to check state and wait for ready
    bool is_ready() const;
    bool has_exception() const;
    bool has_value() const;
    void wait() const;
    template &lt;class Rep, class Period&gt;
    bool wait_for(const chrono::duration&lt;Rep, Period&gt;&amp; rel_time) const;
    template &lt;class Clock, class Duration&gt;
    bool wait_until(const chrono::time_point&lt;Clock, Duration&gt;&amp; abs_time) const;
};
</pre>

<p>Add the following after current paragraph 1:</p>

<pre class="standardtext inserted">
shared_future();
</pre>

<dl class="standardtext inserted">
<dt>Effects:</dt>
<dd>Construct a new instance of <code>shared_future</code> with no
  associated state.</dd>
<dt>Postcondition:</dt>
<dd><code>waitable()</code> returns <code>false</code></dd>
</dl>

<p>Added the following after the current paragraph 2 (effects of copy-constructor)
as follows:</p>

<dl class="standardtext">
  <dt>Postcondition:</dt>
  <dd><span class="inserted">Calling <code>waitable</code>
  on the newly-constructed object returns the same value
  as <code>rhs.waitable()</code>.</span></dd>
</dl>

<pre class="standardtext inserted">
shared_future(shared_future&amp;&amp; rhs);
</pre>

<dl class="standardtext inserted">
<dt>Effects:</dt>
<dd>Transfer the state associated with <code>rhs</code>
  to <code>this</code>.</dd>
<dt>Postcondition:</dt>
<dd>Calling <code>waitable</code> on the newly-constructed object
  returns the same value as <code>rhs.waitable()</code> prior to the
  constructor invocation. <code>rhs.waitable()</code>
  returns <code>false</code>.</dd>
</dl>

<pre class="standardtext inserted">
shared_future&amp; operator=(const shared_future&amp; rhs);
</pre>

<dl class="standardtext inserted">
<dt>Effects:</dt>
<dd>Update <code>this</code> to reference the state associated
  with <code>rhs</code>. If <code>this-&gt;waitable()</code>
  was <code>true</code> prior to the assignment, and there are
  no <code>promise</code>, <code>packaged_task</code> or
  other <code>shared_future</code> instances referencing that state,
  then destroy that state.</dd>
<dt>Postcondition:</dt>
<dd>Calling <code>waitable</code> on the newly-constructed object
  returns the same value as <code>rhs.waitable()</code> prior to the
  assignment invocation. <code>this</code> and <code>rhs</code>
  reference the same associated state.</dd>
</dl>

<pre class="standardtext inserted">
shared_future&amp; operator=(shared_future&amp;&amp; rhs);
</pre>

<dl class="standardtext inserted">
<dt>Effects:</dt>
<dd>Transfer the state associated with <code>rhs</code>
  to <code>this</code>. If <code>this-&gt;waitable()</code>
  was <code>true</code> prior to the assignment, and there are
  no <code>promise</code>, <code>packaged_task</code> or
  other <code>shared_future</code> instances referencing that state,
  then destroy that state.</dd>
<dt>Postcondition:</dt>
<dd>Calling <code>waitable</code> on the newly-constructed object
  returns the same value as <code>rhs.waitable()</code> prior to the
  assignment invocation. <code>rhs.waitable()</code>
  returns <code>false</code>.</dd>
</dl>

<pre class="standardtext inserted">
bool waitable() const;
</pre>

<dl class="standardtext inserted">
<dt>Returns:</dt>
<dd><code>true</code> if <code>this</code> has associated
  state, <code>false</code> otherwise.</dd>
</dl>

<p>Add a new paragraph following the current paragraph 7 as part of
  the description of <code>shared_future::get()</code>:</p>

<dl class="standardtext inserted">
<dt>Precondition:</dt>
<dd><code>waitable()</code>
  returns <code>true</code>.</dd>
</dl>

<p>Add a new paragraph prior to the current paragraph 13 as part of
  the description of <code>shared_future::wait()</code>:</p>

<dl class="standardtext inserted">
<dt>Precondition:</dt>
<dd><code>waitable()</code>
  returns <code>true</code>.</dd>
</dl>

<p>Add a new paragraph prior to the current paragraph 16 as part of
  the description of <code>shared_future::wait_for()</code>:</p>

<dl class="standardtext inserted">
<dt>Precondition:</dt>
<dd><code>waitable()</code>
  returns <code>true</code>.</dd>
</dl>

<p>Add a new paragraph prior to the current paragraph 19 as part of
  the description of <code>shared_future::wait_until()</code>:</p>

<dl class="standardtext inserted">
<dt>Precondition:</dt>
<dd><code>waitable()</code>
  returns <code>true</code>.</dd>
</dl>

<h2>Acknowledgements</h2>

<p>I am grateful to Alisdair Meredith and Jonathan Wakely for their
  comments on drafts of this paper.</p>

</body>
</html>
