
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
    "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta charset="utf-8">
<title>Add parameter preview to coroutine promise constructor</title>
<style type="text/css">
  p {text-align:justify}
  li {text-align:justify}
  blockquote.note
  {
    background-color:#E0E0E0;
    padding-left: 15px;
    padding-right: 15px;
    padding-top: 1px;
    padding-bottom: 1px;
  }
  ins {background-color:#A0FFA0}
  del {background-color:#FFA0A0}
  table {border-collapse: collapse;}
  table, th, td {
    border: 1px solid black;
    border-collapse: collapse;
  }
  
  .docinfo { float: right }
  .docinfo p { margin: 0; text-align:right; }
  .docinfo address { font-style: normal; }
</style>
</head>
<body>
<!--
<div class="docinfo">
    <p>ISO/IEC JTC1 SC22 WG21 P0914R0</p>
    <p>Date: 2018-02-08</p>
    <p>Audience: Evolution</p>
    <address>
      GorNishanov &lt;<a href="mailto:gorn@microsoft.com">gorn@microsoft.com</a>&gt;
    </address>
</div>
-->
<table>
<tr>
<td align="left">Doc. no.</td>
<td align="left">P0914R1</td>
</tr>
<tr>
<td align="left">Revises</td>
<td align="left">P0914R0</td>
</tr>
<tr>
<td align="left">Date:</td>
<td align="left">2018-03-15
</td>
</tr>
<!--
<tr>
<td align="left">Project:</td>
<td align="left">Programming Language C++</td>
</tr>
-->
<tr>
<td align="left">Reference:</td>
<td align="left">ISO/IEC TS 22277, C++ Extensions for Coroutines</td>
</tr>
<tr>
<td align="left">Audience:</td>
<td align="left">EWG</td>
</tr>
<tr>
<td align="left">Reply to:</td>
<td align="left">Gor Nishanov &lt;<a href="mailto:gorn@microsoft.com">gorn@microsoft.com</a>&gt;</td>
</tr>
</table>
<h1>Add parameter preview to coroutine promise constructor</h1>
<h2> Issue </h2>
<!--
<p>All proposed resolutions wording is relative to <a href="https://isocpp.org/files/papers/N4680.pdf">N4680</a> (ISO/IEC TS 22277).</p>

<p><b>Section:</b> 8.4.4 [dcl.fct.def.coroutine] <b>Status:</b> Has wording
 <b>Submitter:</b> Eric Niebler <b>Opened:</b> 2018-02-08 <b>Last modified:</b> 2018-02-08</p>
<p><b>Issue:</b></p>
-->
<p>
  Users of C++ coroutines have long been requesting an ability to access coroutine parameters 
  in the constructor of the coroutine promise. Current workaround is to override 
  <code>operator new</code> of the coroutine promise that does allow observing of 
  coroutine parameters, then extract the value of the desired parameter and store it in 
  a <code>thread_local</code> variable and later extract the value
  from the <code>thread_local</code> in the coroutine promise default constructor and 
  store the value in the coroutine promise.
</p>
<p>
  The workaround used is not reliable as compiler is allowed to elide heap allocation for the coroutine
  state and elide invocation of <code>operator new</code>. Coroutines need direct and reliable way of 
  expressing the desired behavior.
</p>
<p>
  Suggestion is to give a coroutine promise an ability to look at the coroutine parameters.
</p>
<p><b>Before:</b></p>
<pre>
  struct my_promise_type {
    static thread_local cancellation_token saved_tok;
    cancellation_token tok;

    template &lt;typename... Whatever&gt;
    void* operator new(size_t sz, cancellation_token tok, Whatever const&...) {
      // BROKEN: May not get called if heap allocation is elided.
      saved_tok = tok;
      return ::operator new(sz);
    }

    my_promise_type() : tok(saved_tok) {}
    ...
  };
</pre>
  <p><b>After:</b></p>
<pre>
  struct my_promise_type {
    cancellation_token tok;

    template &lt;typename... Whatever&gt;
    my_promise_type(cancellation_token tok, Whatever const&) : tok(tok) {}
    ...
  };
</pre>
    
<h2>Wording:</h2>
<p><i>[Proposed wording is relative to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/n4723.pdf">N4723</a>].</i></p>

<p>Modify paragraph 8.4.4/3 as follows:</p>
<blockquote>
    For a coroutine <i>f</i> that is a non-static member function, let <i>P1</i> denote the type of the 
    implicit object parameter (13.3.1) and <i>P2 ... Pn</i> be the types of the function parameters;
    otherwise let <i>P1 ... Pn</i> be the types of the function parameters. Let <i>p1 ... pn</i> be
    lvalues denoting those objects. Let <i>R</i> be the return type and <i>F</i> be the function-body of
    <i>f</i>, <i>T</i> be the type <code>std::experimental::coroutine_traits&lt;</code><i>R,P1,...,Pn</i><code>&gt;</code>, and
    <i>P</i> be the class type denoted by <i>T</i><code>::promise_type</code>.
    Then, the coroutine behaves as if its body were:  
    <pre>
        {
          <i>P p</i> <ins><i>promise-constructor-arguments</i></ins>;
          co_await <i>p</i>.initial_suspend(); <i>// initial suspend point</i>
          try {
            F 
          } catch(...) { <i>p</i>.unhandled_exception(); }
        <i>final_suspend</i>:
          co_await <i>p</i>.final_suspend(); <i></i>// final suspend point</i>
        }  
      </pre>
      where an object denoted as <i>p</i> is the promise object of the coroutine<ins>,</ins> 
      <del>and</del> its type <i>P</i> is the <i>promise type</i> of the coroutine<ins>, 
      and <i>promise-constructor-arguments</i>
      is determined as follows:
      overload resolution is performed on a promise constructor call created by 
      assembling an argument list with lvalues <i>p</i><sub>1</sub> ... <i>p</i><sub>n</sub>.
      If a viable constructor is found (16.3.2), then <i>promise-constructor-arguments</i>
      is <code>(<i>p</i><sub>1</sub>,</code>...<code>,<i>p</i><sub>n</sub>)</code>,
      otherwise <i>promise-constructor-arguments</i>
      is empty</ins>.
</blockquote>

<p>Modify paragraph 7 of 8.4.4/7 as follows<p>
<blockquote>
An implementation may need to allocate additional storage for a coroutine. 
This storage is known as the coroutine state and is obtained by calling a non-array allocation function (3.7.4.1).
The allocation function’s name is looked up in the scope of <i>P</i>. If this lookup fails, the allocation
function’s name is looked up in the global scope. If the lookup finds an allocation function in the scope of <i>P</i>,
overload resolution is performed on a function call created by assembling an argument list.
The first argument is the amount of space requested, and has type <code>std::size_t</code>. 
The lvalues <i>p1...pn</i> are the succeeding arguments. If no <ins>viable</ins><del>matching</del> function is found <ins>(16.3.2)</ins>,
overload resolution is performed again on a function call created by passing just the amount of space
required as an argument of type <code>std::size_t</code>.
</blockquote>

<p>Add underlined text to 8.4.4/11:<p>
  <blockquote>
    When a coroutine is invoked, a copy is created for each coroutine parameter. Each such copy
    is an object with automatic storage duration that is direct-initialized from an lvalue referring to
    the corresponding parameter if the parameter is an lvalue reference, and from an xvalue referring
    to it otherwise. A reference to a parameter in the function-body of the coroutine <ins>and in the call 
    to the coroutine promise constructor</ins> is replaced by
    a reference to its copy.
  </blockquote>

<h2>Implementation experience</h2>

Implemented in clang trunk.

<!--
<h2>Use cases and history</h2>

<h3> Cancellation </h3>
<pre>
  task&lt;int&gt;(cancellation_token tok) {
    ...
    int i = co_await foo(); // will cancel if tok is signalled
  }
</pre>

<h3> Altering execution context </h3>
<pre>
  task&lt;int&gt;(execution_context ex) {
    ...
    int i = co_await foo(); // continuations will be invoked in a different execution context.
  }
</pre>
-->
</body>
</html>
