<!DOCTYPE html>
<html>
<head>
<title>P0171_ResponseToP0114</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
/* GitHub stylesheet for MarkdownPad (http://markdownpad.com) */
/* Author: Nicolas Hery - http://nicolashery.com */
/* Version: b13fe65ca28d2e568c6ed5d7f06581183df8f2ff */
/* Source: https://github.com/nicolahery/markdownpad-github */

/* RESET
=============================================================================*/

html, body, div, span, applet, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, a, abbr, acronym, address, big, cite, code, del, dfn, em, img, ins, kbd, q, s, samp, small, strike, strong, sub, sup, tt, var, b, u, i, center, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, embed, figure, figcaption, footer, header, hgroup, menu, nav, output, ruby, section, summary, time, mark, audio, video {
  margin: 0;
  padding: 0;
  border: 0;
}

/* BODY
=============================================================================*/

body {
  font-family: Helvetica, arial, freesans, clean, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  color: #333;
  background-color: #fff;
  padding: 20px;
  max-width: 960px;
  margin: 0 auto;
}

body>*:first-child {
  margin-top: 0 !important;
}

body>*:last-child {
  margin-bottom: 0 !important;
}

/* BLOCKS
=============================================================================*/

p, blockquote, ul, ol, dl, table, pre {
  margin: 15px 0;
}

/* HEADERS
=============================================================================*/

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
}

h1 tt, h1 code, h2 tt, h2 code, h3 tt, h3 code, h4 tt, h4 code, h5 tt, h5 code, h6 tt, h6 code {
  font-size: inherit;
}

h1 {
  font-size: 28px;
  color: #000;
}

h2 {
  font-size: 24px;
  border-bottom: 1px solid #ccc;
  color: #000;
}

h3 {
  font-size: 18px;
}

h4 {
  font-size: 16px;
}

h5 {
  font-size: 14px;
}

h6 {
  color: #777;
  font-size: 14px;
}

body>h2:first-child, body>h1:first-child, body>h1:first-child+h2, body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
  margin-top: 0;
  padding-top: 0;
}

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0;
}

h1+p, h2+p, h3+p, h4+p, h5+p, h6+p {
  margin-top: 10px;
}

/* LINKS
=============================================================================*/

a {
  color: #4183C4;
  text-decoration: none;
}

a:hover {
  text-decoration: underline;
}

/* LISTS
=============================================================================*/

ul, ol {
  padding-left: 30px;
}

ul li > :first-child, 
ol li > :first-child, 
ul li ul:first-of-type, 
ol li ol:first-of-type, 
ul li ol:first-of-type, 
ol li ul:first-of-type {
  margin-top: 0px;
}

ul ul, ul ol, ol ol, ol ul {
  margin-bottom: 0;
}

dl {
  padding: 0;
}

dl dt {
  font-size: 14px;
  font-weight: bold;
  font-style: italic;
  padding: 0;
  margin: 15px 0 5px;
}

dl dt:first-child {
  padding: 0;
}

dl dt>:first-child {
  margin-top: 0px;
}

dl dt>:last-child {
  margin-bottom: 0px;
}

dl dd {
  margin: 0 0 15px;
  padding: 0 15px;
}

dl dd>:first-child {
  margin-top: 0px;
}

dl dd>:last-child {
  margin-bottom: 0px;
}

/* CODE
=============================================================================*/

pre, code, tt {
  font-size: 12px;
  font-family: Consolas, "Liberation Mono", Courier, monospace;
}

code, tt {
  margin: 0 0px;
  padding: 0px 0px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px;
}

pre>code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent;
}

pre {
  background-color: #f8f8f8;
  border: 1px solid #ccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px;
}

pre code, pre tt {
  background-color: transparent;
  border: none;
}

kbd {
    -moz-border-bottom-colors: none;
    -moz-border-left-colors: none;
    -moz-border-right-colors: none;
    -moz-border-top-colors: none;
    background-color: #DDDDDD;
    background-image: linear-gradient(#F1F1F1, #DDDDDD);
    background-repeat: repeat-x;
    border-color: #DDDDDD #CCCCCC #CCCCCC #DDDDDD;
    border-image: none;
    border-radius: 2px 2px 2px 2px;
    border-style: solid;
    border-width: 1px;
    font-family: "Helvetica Neue",Helvetica,Arial,sans-serif;
    line-height: 10px;
    padding: 1px 4px;
}

/* QUOTES
=============================================================================*/

blockquote {
  border-left: 4px solid #DDD;
  padding: 0 15px;
  color: #777;
}

blockquote>:first-child {
  margin-top: 0px;
}

blockquote>:last-child {
  margin-bottom: 0px;
}

/* HORIZONTAL RULES
=============================================================================*/

hr {
  clear: both;
  margin: 15px 0;
  height: 0px;
  overflow: hidden;
  border: none;
  background: transparent;
  border-bottom: 4px solid #ddd;
  padding: 0;
}

/* TABLES
=============================================================================*/

table th {
  font-weight: bold;
}

table th, table td {
  border: 1px solid #ccc;
  padding: 6px 13px;
}

table tr {
  border-top: 1px solid #ccc;
  background-color: #fff;
}

table tr:nth-child(2n) {
  background-color: #f8f8f8;
}

/* IMAGES
=============================================================================*/

img {
  max-width: 100%
}
</style>
<style type="text/css">
.highlight  { background: #ffffff; }
.highlight .c { color: #999988; font-style: italic } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { font-weight: bold } /* Keyword */
.highlight .o { font-weight: bold } /* Operator */
.highlight .cm { color: #999988; font-style: italic } /* Comment.Multiline */
.highlight .cp { color: #999999; font-weight: bold } /* Comment.Preproc */
.highlight .c1 { color: #999988; font-style: italic } /* Comment.Single */
.highlight .cs { color: #999999; font-weight: bold; font-style: italic } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .gd .x { color: #000000; background-color: #ffaaaa } /* Generic.Deleted.Specific */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #999999 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .gi .x { color: #000000; background-color: #aaffaa } /* Generic.Inserted.Specific */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #aaaaaa } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { font-weight: bold } /* Keyword.Constant */
.highlight .kd { font-weight: bold } /* Keyword.Declaration */
.highlight .kp { font-weight: bold } /* Keyword.Pseudo */
.highlight .kr { font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #445588; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #009999 } /* Literal.Number */
.highlight .s { color: #d14 } /* Literal.String */
.highlight .na { color: #008080 } /* Name.Attribute */
.highlight .nb { color: #0086B3 } /* Name.Builtin */
.highlight .nc { color: #445588; font-weight: bold } /* Name.Class */
.highlight .no { color: #008080 } /* Name.Constant */
.highlight .ni { color: #800080 } /* Name.Entity */
.highlight .ne { color: #990000; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #990000; font-weight: bold } /* Name.Function */
.highlight .nn { color: #555555 } /* Name.Namespace */
.highlight .nt { color: #000080 } /* Name.Tag */
.highlight .nv { color: #008080 } /* Name.Variable */
.highlight .ow { font-weight: bold } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mf { color: #009999 } /* Literal.Number.Float */
.highlight .mh { color: #009999 } /* Literal.Number.Hex */
.highlight .mi { color: #009999 } /* Literal.Number.Integer */
.highlight .mo { color: #009999 } /* Literal.Number.Oct */
.highlight .sb { color: #d14 } /* Literal.String.Backtick */
.highlight .sc { color: #d14 } /* Literal.String.Char */
.highlight .sd { color: #d14 } /* Literal.String.Doc */
.highlight .s2 { color: #d14 } /* Literal.String.Double */
.highlight .se { color: #d14 } /* Literal.String.Escape */
.highlight .sh { color: #d14 } /* Literal.String.Heredoc */
.highlight .si { color: #d14 } /* Literal.String.Interpol */
.highlight .sx { color: #d14 } /* Literal.String.Other */
.highlight .sr { color: #009926 } /* Literal.String.Regex */
.highlight .s1 { color: #d14 } /* Literal.String.Single */
.highlight .ss { color: #990073 } /* Literal.String.Symbol */
.highlight .bp { color: #999999 } /* Name.Builtin.Pseudo */
.highlight .vc { color: #008080 } /* Name.Variable.Class */
.highlight .vg { color: #008080 } /* Name.Variable.Global */
.highlight .vi { color: #008080 } /* Name.Variable.Instance */
.highlight .il { color: #009999 } /* Literal.Number.Integer.Long */
.pl-c {
    color: #969896;
}

.pl-c1,.pl-mdh,.pl-mm,.pl-mp,.pl-mr,.pl-s1 .pl-v,.pl-s3,.pl-sc,.pl-sv {
    color: #0086b3;
}

.pl-e,.pl-en {
    color: #795da3;
}

.pl-s1 .pl-s2,.pl-smi,.pl-smp,.pl-stj,.pl-vo,.pl-vpf {
    color: #333;
}

.pl-ent {
    color: #63a35c;
}

.pl-k,.pl-s,.pl-st {
    color: #a71d5d;
}

.pl-pds,.pl-s1,.pl-s1 .pl-pse .pl-s2,.pl-sr,.pl-sr .pl-cce,.pl-sr .pl-sra,.pl-sr .pl-sre,.pl-src,.pl-v {
    color: #df5000;
}

.pl-id {
    color: #b52a1d;
}

.pl-ii {
    background-color: #b52a1d;
    color: #f8f8f8;
}

.pl-sr .pl-cce {
    color: #63a35c;
    font-weight: bold;
}

.pl-ml {
    color: #693a17;
}

.pl-mh,.pl-mh .pl-en,.pl-ms {
    color: #1d3e81;
    font-weight: bold;
}

.pl-mq {
    color: #008080;
}

.pl-mi {
    color: #333;
    font-style: italic;
}

.pl-mb {
    color: #333;
    font-weight: bold;
}

.pl-md,.pl-mdhf {
    background-color: #ffecec;
    color: #bd2c00;
}

.pl-mdht,.pl-mi1 {
    background-color: #eaffea;
    color: #55a532;
}

.pl-mdr {
    color: #795da3;
    font-weight: bold;
}

.pl-mo {
    color: #1d3e81;
}
.task-list {
padding-left:10px;
margin-bottom:0;
}

.task-list li {
    margin-left: 20px;
}

.task-list-item {
list-style-type:none;
padding-left:10px;
}

.task-list-item label {
font-weight:400;
}

.task-list-item.enabled label {
cursor:pointer;
}

.task-list-item+.task-list-item {
margin-top:3px;
}

.task-list-item-checkbox {
display:inline-block;
margin-left:-20px;
margin-right:3px;
vertical-align:1px;
}
</style>
</head>
<body>
<table>
<thead>
<tr>
<th>Document Number:</th>
<th>P0171R0</th>
</tr>
</thead>
<tbody>
<tr>
<td>Date:</td>
<td>2015-11-06</td>
</tr>
<tr>
<td>Audience:</td>
<td>Evolution</td>
</tr>
<tr>
<td>Revises:</td>
<td>none</td>
</tr>
<tr>
<td>Reply to:</td>
<td>Gor Nishanov (gorn@microsoft.com)</td>
</tr>
</tbody>
</table>
<h1 id="response-to-resumable-expressions-p0114r0">Response To: Resumable Expressions P0114R0</h1>
<p>This paper is in response to concerns expressed in the resumable expressions paper <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a>. We include brief quotes as a quick reminder of the concerns being discussed. Readers are encouraged to refer to <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a> for full context. Familiarity with <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0054r0.html">P0054</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0055r0.html">P0055</a>, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> and <a href="https://isocpp.org/files/papers/N4402.pdf">N4402</a> is highly desired.</p>
<h2 id="when-scheduling-logic-embedded-in-the-language">When scheduling logic embedded in the language</h2>
<pre><code>(Section 1.1) ... design choices in N4402 ... introduce the potential for unfairness and starvation.
(Section 4.5) This design, where await prefers to avoid coroutine suspension if it can, 
              is a bad default. It leads to unfairness, jitter, and starvation.
</code></pre><p>We completely agree with <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a> that </p>
<ul>
<li>scheduling logic should not be embedded in the language </li><li>favoring synchronous completion leads to unfairness, jitter, and starvation. </li></ul>
<p>Luckily <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> does none of those things. <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> offers pure syntactic sugar and the responsibility for making such decisions is left to the library writer. In this particular case, it is not a job of a compiler to second guess a library-provided awaitable that says that suspend is not required.</p>
<p>In this concrete case, the responsibility lies with the implementor of </p>
<pre><code>future&lt;Message&gt; receive_message(Connection&amp; c);
</code></pre><p>In a case of a synchronous completion, a good async I/O library writer would have returned a future that is not ready and provided the result in <code>.get()</code> or to <code>.then</code>. In fact, to even make such a future as described in <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a>, the library writer had to do the work to avoid safe defaults selected by the operating system.</p>
<p>For example, on Windows, even for synchronous API completions, notifications are always sent to a completion queue to be processed in the same way as any asynchronous completion. To suppress this behavior, a library writer would have to write the following:</p>
<pre><code>// ascertain that a particular socket provider has support for sync completions:

WSAPROTOCOL_INFOW wsaProtocolInfo;
int wsaProtocolInfoSize = sizeof(wsaProtocolInfo);
iResult = getsockopt(
    s.native_handle(),
    SOL_SOCKET,
    SO_PROTOCOL_INFOW,
    reinterpret_cast&lt;char*&gt;(&amp;wsaProtocolInfo),
    &amp;wsaProtocolInfoSize);
panic_if(iResult == SOCKET_ERROR, &quot;SOL_SOCKET&quot;);

syncCompletionPossible = (wsaProtocolInfo.dwServiceFlags1 &amp; XP1_IFS_HANDLES) != 0;

if (syncCompletionPossible)
    SetFileCompletionNotificationModes(s.native_handle(),  
        FILE_SKIP_COMPLETION_PORT_ON_SUCCESS);
</code></pre><p>Even in those cases where library writer have chosen suboptimal behavior for awaitables returned from their asynchronous APIs, such as <code>receive_message</code> above, P0054 offers <code>await_transform</code> customization point which allows coroutine author to overwride defaults provided by the library writer. </p>
<h2 id="we-must-remember-to-annotate-the-call-with-an-await-keyword">We must remember to annotate the call with an await keyword</h2>
<pre><code>(Section 4.1): ... whenever we make a call to a resumable function we 
               must remember to annotate the call with an await keyword.
               Failure to do so can result in hard to diagnose bugs ...
</code></pre><p>We completely agree that as the C++ language stands today, it is too easy to forget to handle the result of the function / constructor. We can see those mistakes made with terrifying frequency. It is so bad that some companies resorted to using macros, such as ACQUIRE_LOCK(m) as to avoid making the mistake of these kind:</p>
<pre><code>lock_guard&lt;mutex&gt; (m); // oops, lock is acquired and released before &#39;;&#39;
   instead of
lock_guard&lt;mutex&gt; _(m); // aha, now it will work as we wanted
</code></pre><p>Similarly, one of the famous misuses of <code>std::async</code> results in the following code executing a, b, c and d sequentially.</p>
<pre><code>a();
std::async([]{b();});
std::async([]{c();});
d();
</code></pre><p>We were working on a proposal to address that, but, luckily, Andrew Tomazos beat us to it and offered <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0068r0.pdf">NoDiscard</a> paper addressing this concern. Annotating functions/classes with <code>[[nodiscard]]</code> attribute allows to catch mistakes at compile time as shown in the example below.</p>
<pre><code>[[nodiscard]] future&lt;int&gt; Connection::Read(void* buf, size_t len);

template &lt;typename Mutex&gt; [[nodiscard]] class lock_guard;

future&lt;void&gt; f(Connection&amp; c) {
   ...
   c.Read(buf, sizeof(buf)); // error: the return value of Read is discarded
   lock_guard&lt;mutex&gt; (m); // error: the return value of the constructor is discarded
}
</code></pre><h2 id="-if-we-had-direct-access-to-the-implementation-type-__foo-we-could-write-an-efficient-batching_generator-int-">[If we had] direct access to the implementation type __foo, we could write an efficient ... batching_generator<int></h2>
<p>All generator implementations shown in papers <a href="https://isocpp.org/files/papers/N4402.pdf">N4402</a> (and previous versions), <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> (and previous versions) rely on direct access to the relevant parts of the coroutine data structures. </p>
<p>Let&#39;s take a look at <a href="https://isocpp.org/files/papers/N4402.pdf">N4402</a> &quot;appendix A&quot; that shows an example of a generator. We pasted here relevant snippets:</p>
<pre><code>template &lt;typename T&gt;
struct generator {
  struct promise_type {
    T const * CurrentValue;
    ...
    void yield_value(T const&amp; value) { CurrentValue = addressof(value); }
  };
  struct iterator : std::iterator&lt;input_iterator_tag, T&gt; {
     coroutine_handle&lt;promise_type&gt; coro;
     T const&amp; operator*() const { return *coro.promise().CurrentValue; }
     ...
</code></pre><p>An object of a <code>promise_type</code> type resides inside of the coroutine internal state and direct access is provided by <code>coroutine_handle::promise()</code>.</p>
<p>In this example, when control flow reaches <code>yield expr;</code>, the coroutine is suspended, a pointer to an expression is stored in the coroutine promise and the consumer dereferences the iterator and gets direct access to the expression being yielded without any moves or copies.</p>
<p>It is trivial to write a <code>batching_generator&lt;T&gt;</code>, but in this case, a simple generator as shown in <a href="https://isocpp.org/files/papers/N4402.pdf">N4402</a> or <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> will be more efficient. Because...</p>
<h2 id="what-compiler-giveth-compiler-taketh-away">What compiler giveth compiler taketh away</h2>
<pre><code>(Section 3) ... we are not required to use a type-erased container
(Section 4.3) Type erasure and fine grained polymorphism
   Every value produced by the generator requires an indirect function call.
   By embedding fine-grained type erasure into the language, we are denied 
   the opportunity to develop library abstractions that amortise the cost of
   runtime polymorphism.
(Section 4.4) Rather than minimising the abstraction penalty, a consequence of
   N4402 resumable functions’ type erasure is that they exhibit poor scalability
</code></pre><p>These indeed are grave concerns but they are inapplicable to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a>. As discussed in the Urbana, <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> (and Urbana&#39;s <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4134.pdf">N4134</a>) allows a compiler to choose under which conditions type erasure needs to be performed and when it can be elided. </p>
<p>When a coroutine&#39;s lifetime is fully enclosed in the lifetime of its caller, no type erasure, indirect calls or memory allocations need to be done, which are exactly the cases when <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a> does not need type erasure. However, when you want to put a coroutine on an ABI boundary and/or use it for asynchronous scenarios, the compiler will do it for you which avoids the need to write boilerplate code. Moreover, in Urbana we discussed how this optimization can work even across ABI boundaries.</p>
<p>We are not aware of any circumstances where a solution written using the abstractions of <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a> will be more efficient than the same problem being solved using abstractions offered by <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> and we have a case where abstractions of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> results in strictly better efficiency than <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a>. For example, compare the negative overhead await adapters from <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4287.pdf">N4287</a> with await library emulation shown in <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a>. </p>
<h2 id="a-very-costly-maintenance-nightmare">A very costly maintenance nightmare</h2>
<pre><code>(Section 3) ... the maintenance burden of a viral await keyword
(Section 4.1) Experiences with other languages that take a similar approach 
   (such as Python) have shown that this quickly becomes a very costly maintenance nightmare.
</code></pre><p>We weren&#39;t able to obtain the source for the information for the claims above, so we had to resort to our own research.</p>
<p>Since C# was the first language that acquired this exact syntax in 2012, we contacted the C# design team and the C# program management teams to learn about their experience. They were not aware of any studies on that matter and commented that delight and joy is the usual reaction of people who use the <code>await</code> feature extensively.</p>
<p>Moreover, the await syntax proved extremely useful and popular and more languages adopted it to solve their asynchronous blues, <a href="http://docs.hhvm.com/manual/en/hack.async.php">HACK</a> and <a href="http://queue.acm.org/detail.cfm?id=2747873">Dart</a> in 2014, Python (<a href="https://www.python.org/dev/peps/pep-0492/">PEP0492</a>) in May of 2015 and it seems to be on track to get into <a href="http://blogs.msdn.com/b/eternalcoding/archive/2015/09/30/javascript-goes-to-asynchronous-city.aspx">EcmaScript7</a> soon.</p>
<p>Since we are on the subject of maintenance nightmares, we would like to offer a conjecture that the absence of the await in <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a> is a likely source of many maintenance nightmares. Without a syntactic marker to signal to the person reading the code that something funny is going on, it is impossible to tell whether the following code is correct or not:</p>
<pre><code>auto foo(string &amp; s) {
   s.push_back(&#39;&lt;&#39;);
   do-stuff
   s.push_back(&#39;&gt;&#39;);
}
</code></pre><p>How can we be sure that <em>do-stuff</em> will never result in suspension? Should we follow all of the possible call sequences to make sure that none of them lead to <code>break resumable;</code>?</p>
<p>Note, that this code is fine to be used with fibers or threads, because in that case the entire stack is suspended, so the caller which owns <code>s</code> will be suspended as well, thus avoiding mismatched lifetimes.</p>
<p>In coroutines the suspend point is clearly marked with <code>await</code>, which tells the reader that something unusual happens in this function and allows the reader, for example, to confirm whether the lifetimes of the objects of interest align with the lifetime of the coroutine or not, whether some locks need to be acquired to protect some concurrently accessed data, and whether some locks need to be released before the execution reaches the suspend point. </p>
<p>Note, that <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0054r0.html">P0054</a> describes how such &#39;no-await-required&#39; behavior can be optionally built on top of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a>, however, due to our grave concerns about maintainability of such code we recommend against it.</p>
<h2 id="island-of-abstractions">Island of abstractions</h2>
<pre><code>(Section 4.2) Over time we may end up with a complete set of await-enabled algorithms 
              that mirror the existing standard algorithms. These algorithms will be 
              independent and not interoperable with the existing algorithms
</code></pre><p>Does it have to be the way <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a> describes? We don&#39;t believe so.</p>
<p>Embracing coroutines makes existing libraries better and leads to smaller API surface.<br>Paper <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0055r0.html">P0055</a> shows how to extend the CompletionToken model so that any library that follows that model will automatically gain “negative-overhead” behavior compared to what they get with a callback model and retain the performance if they use callbacks.</p>
<p>The beauty of it is that it is automatic. Providing a low level API with a particular shape and a trivial templated high level wrapper allows the CompletionToken transform to do the magic. When used with coroutines, suddenly the libraries that used to do memory allocation and type erasure for every single async operation, no longer will have to. This affects the networking proposal, boost::asio, executors, etc. An additional benefit is that it reduces the number of APIs that a library needs to provide as shown at the end of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0055r0.html">P0055</a> paper.</p>
<p>The benefit of this approach extends beyond the networking library to other future standard or non-standard libraries modeling their APIs on the CompletionToken/completion_token_transform.</p>
<h2 id="conclusion">Conclusion</h2>
<p>We agree with most of the concerns expressed by <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a>, however all but one are not relevant to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a>. The concern that is relevant (mistake of not using the result of a function/constructor) is not unique to coroutines and is tackled by paper <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0068r0.pdf">NoDiscard</a>.</p>
<p>Our position is that for any concrete problem that can be solved with the abstractions offered by <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">P0114</a>, the same problem can be solved with the abstractions offered by <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a> with equal or superior characteristics of:</p>
<ul>
<li>how much code end-user have to write to solve the problem</li><li>how much library support required to enable the abstraction</li><li>what is the abstraction penalty  </li></ul>
<h2 id="references">References</h2>
<p><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4287.pdf">N4287</a>: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4287.pdf">Threads, Fibers and Couroutines (slides deck)</a><br><a href="https://isocpp.org/files/papers/N4402.pdf">N4402</a>: <a href="https://isocpp.org/files/papers/N4402.pdf">Resumable Functions (revision 4)</a><br><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0054r0.html">P0054</a>: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0054r0.html">Coroutines: Reports from the field</a><br><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0055r0.html">P0055</a>: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0055r0.html">On Interactions Between Coroutines and Networking Library</a><br><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">P0057</a>: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0057r0.pdf">Wording for Coroutines rev3</a><br><a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">p0114</a>: <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf">Resumable Expressions (revision 1)</a><br><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0068r0.pdf">NoDiscard</a>: <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0068r0.pdf">P0068: Proposal of &quot;unused&quot;, &quot;nodiscard&quot; and &quot;fallthrough&quot; attributes.</a></p>
<p><a href="https://www.python.org/dev/peps/pep-0492/">PEP0492</a>: <a href="https://www.python.org/dev/peps/pep-0492/">Coroutines with async and await syntax</a><br><a href="http://blogs.msdn.com/b/eternalcoding/archive/2015/09/30/javascript-goes-to-asynchronous-city.aspx">EcmaScript7</a>: <a href="http://blogs.msdn.com/b/eternalcoding/archive/2015/09/30/javascript-goes-to-asynchronous-city.aspx">JavaScript goes to Asynchronous city</a><br><a href="http://docs.hhvm.com/manual/en/hack.async.php">HACK</a>: <a href="http://docs.hhvm.com/manual/en/hack.async.php">Hack Language Reference</a><br><a href="http://queue.acm.org/detail.cfm?id=2747873">Dart</a>: <a href="http://queue.acm.org/detail.cfm?id=2747873">Spicing Up Dart with Side Effects</a></p>
<!--
[N4286]: http://open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4286.pdf
[N4134]: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4134.pdf
[N4361]: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4361.pdf
[N4466]: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4466.pdf
[N4513]: http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4513.pdf
[N4527]: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4527.pdf
[N4453]: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/n4453.pdf 
[N4499]: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4499.pdf
[p0055]: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0055r0.html 

[p0057]: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0057r0.pdf
[p0114]: http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf 
[p0114]: [Resumable Expressions (revision 1)](http://open-std.org/JTC1/SC22/WG21/docs/papers/2015/p0114r0.pdf) 
papers/2015/p0057r0.pdf)
[N4402]: [Resumable Functions (revision 4)](https://isocpp.org/files/papers/N4402.pdf)
[NoDiscard]: Proposal of [[unused]], [[nodiscard]] and [[fallthrough]] attributes.
-->
<!--
## References

DEAD-WRONG-SCHEDULING: [4]
    (6) up and out impact performance & introduce potential for unfairness and starvation
    (23) when scheduling logic embedded in the language
    (24) we need to always return false


On Boilerplate:

## Introduction

The starting point for my proposal was lambda-star. A lambda that keeps all of the objects with automatic storage duration from the body in the closure object. I wanted an abstraction that is more fundamental than what was offered by earlier await proposals pre-N4134 and awaits in other languages, but the one, on top of which I can efficiently build C# like await syntax. After running around with that idea for a month I came to the conclusion that when applied to concrete problems, it requires more boilerplate code and does not result in more efficient code. Moreover, in those cases where you don't need to allocate lambda-star on the heap and can place it on the stack, A compiler could infer the coroutine lifetime and elide heap allocation, thus again resulting in the same efficiency. Hence, I tabled lambda* until better times. 

Chris proposal suffers from the same problem as lambda*. It requires you to write more code as a user without providing tangible benefit. As I said before, for any concrete problem, you will get the same or more efficient code with my proposal than with Chris'es. Thus, there is no justification for added complexity.




Look at the async state machine problem which I discussed in the http://wg21.link/N4287. Or look at http://wg21.link/P0055 which explains how await SomeAsyncOp is expanded. Now, compare what does it take to get from await f() in my proposal and await(f()) or f(use_await) in P0114R0 to the actual OS call. Abstraction overhead is lower in P0057.




On Optimizations




C++ is a language that offers an ability to create zero-overhead abstractions (or negative overhead in case of P0057). However, zero-overhead part comes from the optimizer. When STL was first proposed in 1994, no compiler in the world could make it efficient. It took more than ten years before compilers caught up. Optimization technology is fundamental to C++ abstractions. 




Await or Not




If you look at http://wg21.link/P0054, you will find a section "Exploring design space" which sketches out how you can evolve P0057 to add the "magic" so that you don't have to write awaits. However, I am not sure that absence of explicit indication of suspend points is a good thing, but, may get convinced otherwise in the future.

OPTIMIZABLE [1]
    (1) no hidden memory allocations
    (10) May incorporate with the same cost as a normal function call
    (12) not required to use a type-erased container to represent the resumable function object
    (19) cost of indirect call and no opportunity for inline, every value produced by a generator requires indirect call
    (22) indirect calls in await example

AAA [2]
    (3) viral control flow + suspend down - lie
    (4) code reuse between stackless, stackful & normal threads
    (8) without peppering each async call with await (viral)
    (11) we have the flexibility introducing resumable functions further down the call tree (illusion)
    (25) BS about ability syntactical suspend down
    (14) viral impact

INTERACTION-WITH-TEMPLATES [3]
    (13) reusing output iterator (AAA + better algo)
    (17) island of abstractions (resu_for_each)
    (26) BS about completionToken

DEAD-WRONG-SCHEDULING: [4]
    (6) up and out impact performance & introduce potential for unfairness and starvation
    (23) when scheduling logic embedded in the language
    (24) we need to always return false

MAINTAINABILITY [5]
    (7) significant cost in terms of maintainability and usability
    (15) very costly maintenance nightmare

BATCHING-GENERATOR: [6]
    (18) cannot get to underline object
    (20) not supportinng arbirary gen types
    (21) cannot do batching generator

NO NEED TO ARGUE
SILLY
    (2) only one new keyword
SAME
    (5) provide a building block for resumable control flow patterns
    (9) there is no need to use future, yep
TRUE
    (16) nodiscard


## Introduction

Coroutine proposal [P0057R0] provides abstractions capturing common patterns dealing with asynchronous programming. Language facilities provide syntactic sugar and the semantic is left to the library. In a way it is analogous to a range-based-for, where the syntax language construct for(x: Y) communicates with any Y that satisfy the requirements specified in [stmt.ranged], but, by itself, range-based for has no knowledge of containers or other entities it is used to iterate over.

Unlike range-base-for, thought, coroutines do not have an equivalent lower level facility such as `for(;;)` or even `goto`. Currently, the only way to access the low-level coroutine machinery is via high-level abstractions of [P0057R0]. 

Thus we welcome resumable expression paper [P0114r0] looking for lower-level facility on which  


## Introduction

This paper is in response to [P0114r0]: Resumable Expressions (revision 1). The paper raises some concerns about Coroutine proposal [N4499]. We would like to address them. Further in this paper, the coroutine proposal would refer to N4499 and its more recent incarnation [p0057r0]. The paper will refer to [P00114R0].

## Ranged-based for analogy

Currently, with proposal 

Looking for for(;;)

With Coroutine propos

Furthermore, resumable exp 

## When scheduling logic is embedded in the language

The paper inaccurately asserts that scheduling logic is embedded in the coroutine proposal. Coroutine proposal provides syntactic sugar and it is up to the user of the coroutine or developer of coroutine aware libraries to make appropriate scheduling decision. 

For more details on how an asynchronous library can efficiently interact with coroutines, see "[p0055r0]: On Interactions Between Coroutines and Networking Library".

## A very costly maintenance nightmare

The paper asserts:

    Experiences with other languages that take a similar approach (such as Python)
    have shown that this quickly becomes a very costly maintenance nightmare.

We contacted the author for the source for this information and did not get a response.
For the reference, Python only got the support for await in May of 2015. We contacted C# team where await was available since 2012 and they were not aware of any reports of maintenance nightmare resulting in C# usage of await keyword.  
-->

</body>
</html>
<!-- This document was created with MarkdownPad, the Markdown editor for Windows (http://markdownpad.com) -->
