<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <meta http-equiv="Content-Style-Type" content="text/css" />
  <meta name="generator" content="pandoc" />
  <title></title>
  <style type="text/css">code{white-space: pre;}</style>
  <style type="text/css">
div.sourceCode { overflow-x: auto; }
table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode {
  margin: 0; padding: 0; vertical-align: baseline; border: none; }
table.sourceCode { width: 100%; line-height: 100%; }
td.lineNumbers { text-align: right; padding-right: 4px; padding-left: 4px; color: #aaaaaa; border-right: 1px solid #aaaaaa; }
td.sourceCode { padding-left: 5px; }
code > span.kw { color: #007020; font-weight: bold; } /* Keyword */
code > span.dt { color: #902000; } /* DataType */
code > span.dv { color: #40a070; } /* DecVal */
code > span.bn { color: #40a070; } /* BaseN */
code > span.fl { color: #40a070; } /* Float */
code > span.ch { color: #4070a0; } /* Char */
code > span.st { color: #4070a0; } /* String */
code > span.co { color: #60a0b0; font-style: italic; } /* Comment */
code > span.ot { color: #007020; } /* Other */
code > span.al { color: #ff0000; font-weight: bold; } /* Alert */
code > span.fu { color: #06287e; } /* Function */
code > span.er { color: #ff0000; font-weight: bold; } /* Error */
code > span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
code > span.cn { color: #880000; } /* Constant */
code > span.sc { color: #4070a0; } /* SpecialChar */
code > span.vs { color: #4070a0; } /* VerbatimString */
code > span.ss { color: #bb6688; } /* SpecialString */
code > span.im { } /* Import */
code > span.va { color: #19177c; } /* Variable */
code > span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code > span.op { color: #666666; } /* Operator */
code > span.bu { } /* BuiltIn */
code > span.ex { } /* Extension */
code > span.pp { color: #bc7a00; } /* Preprocessor */
code > span.at { color: #7d9029; } /* Attribute */
code > span.do { color: #ba2121; font-style: italic; } /* Documentation */
code > span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code > span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code > span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
  </style>
</head>
<body>
<h1 id="networking-ts-issues">Networking TS Issues</h1>
<ul>
<li>Document number: <strong>P0703R0</strong>, ISO/IEC JTC1 SC22 WG21</li>
<li>Date: 2017-06-18</li>
<li>Authors: David Sankel <a href="mailto:dsankel@bloomberg.net">dsankel@bloomberg.net</a></li>
<li>Audience: LEWG</li>
</ul>
<h2 id="abstract">Abstract</h2>
<p>This paper provides elaboration of US9 and US10 ballot comments on the <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4656.pdf">Networking TS</a> as requested by LEWG at the Kona 2017 meeting. In summary, Bloomberg formed a committee of networking experts to discuss the Networking TS and concluded that there were a couple usability concerns that should be addressed.</p>
<h2 id="us9">US9</h2>
<p>Original text:</p>
<blockquote>
<p>The <code>CompletionToken</code> mechanism used to determine the return types of initiating functions has teachability drawbacks due to its complexity. Also, there would be a high cost if users were to replicate this kind of interface in medium and higher-level libraries built upon the Networking TS. A simpler interface whereby initiating functions have invokable parameters is sufficiently extendable, as they are, to work with futures.</p>
</blockquote>
<p>Suggested resolution:</p>
<blockquote>
<p>Make initiating functions use invokable callbacks instead of completion tokens as in Boost.ASIO.</p>
</blockquote>
<p>Asynchronous operations (called initiating functions) in the Networking TS follow a pattern where a <code>CompletionToken</code> parameter controls both the return value of the function and how the calling code is notified of the operation's completion. For example, see the specification of one of the <code>async_connect</code> overloads:</p>
<div class="sourceCode"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span class="kw">template</span>&lt;<span class="kw">class</span> Protocol, <span class="kw">class</span> InputIterator,
<span class="kw">class</span> ConnectCondition, <span class="kw">class</span> CompletionToken&gt;
DEDUCED async_connect(basic_socket&lt;Protocol&gt;&amp; s,
                      <span class="at">const</span> EndpointSequence&amp; endpoints,
                      ConnectCondition c,
                      CompletionToken&amp;&amp; token);</code></pre></div>
<p>The <code>CompletionToken</code>-related behavior is specified as follows:</p>
<blockquote>
<p>An initiating function determines the type <code>CompletionHandler</code> of its completion handler function object by performing <code>typename</code> <code>async_result&lt;decay_t&lt;CompletionToken&gt;, Signature&gt;::completion_handler_type</code>. The completion handler object <code>completion_handler</code> is initialized with <code>std::forward&lt;CompletionToken&gt;(token)</code>.</p>
</blockquote>
<p>, where,</p>
<blockquote>
<p>The <code>async_result</code> class template is a customization point for asynchronous operations. Template parameter <code>CompletionToken</code> specifies the model used to obtain the result of the asynchronous operation. Template parameter <code>Signature</code> is the call signature (C++Std [func.def]) for the completion handler type invoked on completion of the asynchronous operation</p>
</blockquote>
<p>.</p>
<p>If the <code>CompletionToken</code> is a callback, the asynchronous operation will simply schedule a call to the callback with the result of the operation. If the <code>CompletionToken</code> is <code>use_future</code>, then the result of the operation will be a <code>std::future</code> object that is fulfilled with result of the operation (or rejected with an exception object that includes the error). The benefits of this approach are two-fold: with one function we support both callbacks and futures, and we provide an extension mechanism for supporting any other future-callback-like mechanism.</p>
<p>While this is a clever way to solve the problem, we feel that having a simple callback would be superior. First, the mechanism by which the completion token influences the behavior of the function is difficult to understand and explain. Second, plain callbacks, as the simplest way to signal asynchronous completions, are sufficient for building future-based interfaces on top.</p>
<p>Overall, we feel that a lower-level, and much simpler, callback interface would better serve the needs of the C++ and networking community.</p>
<h2 id="us10">US10</h2>
<p>Original Text:</p>
<blockquote>
<p>Without knowing more about what kind of executor is being used, a user will have difficulty deciding which of the three functions to use to add a task to an executor. It is preferable to limit the options for adding tasks to a generic executor. Concrete executors can add additional functions if required.</p>
</blockquote>
<p>Suggested Resolution:</p>
<blockquote>
<p>Remove the defer function from executors, as that is the least well-defined. This would match the existing Boost ASIO implementation.</p>
</blockquote>
<p>The current Networking TS proposal has three ways to schedule a &quot;task&quot; with an executor: <code>dispatch</code>, <code>post</code>, and <code>defer</code>. To paraphrase section 13.2.2:</p>
<dl>
<dt><code>dispatch(f)</code></dt>
<dd>May call <code>f</code> immediately and wait for it to complete before <code>dispatch</code> returns, otherwise schedule <code>f</code> to be executed.
</dd>
<dt><code>post(f)</code> and <code>defer(f)</code></dt>
<dd>Schedule <code>f</code> to be executed. Neither <code>post</code> nor <code>defer</code> may block on <code>f</code>'s completion.
</dd>
</dl>
<p>While <code>post</code> and <code>defer</code> have identical semantics, the following note is adjoined in the Networking TS text:</p>
<blockquote>
<p>Note: Although the requirements placed on <code>defer</code> are identical to post, the use of <code>post</code> conveys a preference that the caller does not block the first step of <code>f1</code>’s progress, whereas <code>defer</code> conveys a preference that the caller does block the first step of <code>f1</code>. One use of <code>defer</code> is to convey the intention of the caller that <code>f1</code> is a continuation of the current call context. The executor may use this information to optimize or otherwise adjust the way in which <code>f1</code> is invoked.</p>
</blockquote>
<p>The idea is that the writer of a component who is aware of the executor being used can squeeze out some additional performance by choosing <code>defer</code> or <code>post</code> correctly.</p>
<p>We find the difference between <code>post</code> and <code>defer</code> to be too subtle and too executor-specific to be useful in the C++ standard. The confusion caused outweighs the performance gain in the Bloomberg committee's opinion. Additionally, it has not been demonstrated that performance gains from having a distinction between <code>post</code> and <code>defer</code> make a difference in any real-world applications.</p>
<p>For applications that really need a <code>post</code> and <code>defer</code> distinction, we suggest use of a custom executor class that provides the additional operations; these applications are specialized enough to warrant knowledge of the specific executor they are used with.</p>
<h2 id="conclusion">Conclusion</h2>
<p>In summary, we feel the Networking TS should be simplified in the areas of completion tokens and executor interface to best serve the C++ community.</p>
</body>
</html>
