<html><head><meta charset="UTF-8">
<title>Wording for Networking PDTS ballot comments on reentrancy</title>
  <style type='text/css'>
  body {font-variant-ligatures: none;}
  p {text-align:justify}
  li {text-align:justify}
  blockquote.note, div.note
  {
          background-color:#E0E0E0;
          padding-left: 15px;
          padding-right: 15px;
          padding-top: 1px;
          padding-bottom: 1px;
  }
  p code {color:navy}
  ins p code {color:#00A000}
  p ins code {color:#00A000}
  p del code {color:#A00000}
  ins {color:#00A000}
  del {color:#A00000}
  table#boilerplate { border:0 }
  table#boilerplate td { padding-left: 2em }
  table.bordered, table.bordered th, table.bordered td {
    border: 1px solid;
    text-align: center;
  }
  ins.block {color:#00A000; text-decoration: none}
  del.block {color:#A00000; text-decoration: none}
  #hidedel:checked ~ * del, #hidedel:checked ~ * del * { display:none; visibility:hidden }
  </style>
</head><body>
<table id="boilerplate">
<tr><td>Document number</td><td>P0748R0</td></tr>
<tr><td>Date</td><td>2017-07-14</td></tr>
<tr><td>Project</td><td>Programming Language C++, Library Working Group</td></tr>
<tr><td>Reply-to</td><td>Jonathan Wakely &lt;cxx&#x40;kayari.org&gt;</td></tr>
</table><hr>
<h1>Wording for Networking PDTS ballot comments on reentrancy</h1>
<h2>Introduction</h2>

<p>This paper presents proposed changes in response to four National Body comments for PDTS 19216 from <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4643.pdf">N4643</a>.
The comments all relate to reentrancy rules.</p>

<h2>Changes</h2>

<h3>NB comment 008 (GB-3)</h3>

<blockquote><p>Reentrancy and run/dispatch.<br/>
In 17.6.5.8 [reentrancy] the C++14 standard says:<br/>
"Except where explicitly specified in this standard, it is implementation-defined which functions in the Standard C++ library may be recursively reentered."<br/>
In the executor requirements, the intention is that the dispatch() function may be recursively reentered. A statement to this effect may need to be added to the requirements. (All dispatch() member functions provided by executors in the TS itself should then by implication allow reentrancy.)</p>

<p><strong>Proposed change:</strong>
Explicitly specify that dispatch functions can be recursively re-entered.</p></blockquote>

<p>Accept the change.</p>

<h3>NB comment 015 (GB-6)</h3>

<blockquote><p>Reentrancy and use_service/make_service.<br/>
The intention is that both use_service and make_service may make nested calls (from the Service constructor) to use_service or make_service. Obviously these nested calls will require a different Service template argument. I am uncertain if calling these function templates with different template arguments counts as recursive reentrance, but if it does then we may need to add a sentence explicitly specifying that this is permitted.</p>

<p><strong>Proposed change:</strong>
Decide if it's needed and add a suitable sentence.</p></blockquote>

<p>Accept the change.</p>

<p>LWG noticed some underspecification in 13.7 [async.exec.ctx] which makes specifying this difficult.
I have tried to address that.</p>

<h3>NB comment 016 (GB-7)</h3>

<blockquote><p>run()/run_one() specification overly restrictive on users.<br/>
Both the run() and run_one() functions include the following statement:<br/>
"Must not be called from a thread that is currently calling a run function."<br/>
This restriction was originally added as a way to prevent users from entering a kind of "deadlock". This is because run() and run_one() can block until the io_context runs out of work. Since outstanding work includes currently executing function objects, if a function object makes a nested call to run()/run_one() that nested call could block forever as the work count can never reach zero.<br/>
However, it has been brought to Chris Kohlhoff's attention by users that there are valid use cases for making these nested calls. Deadlock can be avoided if some other condition will cause run()/run_one() to exit (e.g. an exception, explicit call to stop, run_one finished running a single function, etc). This condition can be known ahead of time by the user.<br/>
The existing implementation in asio does not make any beneficial use of this restriction.</p>

<p><strong>Proposed change:</strong> Strike those sentences from both those places. Make it the responsibility of the user to avoid the conditions for deadlock.</p></blockquote>

<p>Accept the change, adding notes warning about the potential for deadlock.</p>

<h3>NB comment 017 (GB-8)</h3>

<blockquote><p>Reentrancy and run functions.<br/>
The intention is that the run functions may be recursively reentered. We may want add a sentence explicitly specifying this.</p>

<p><strong>Proposed change:</strong>
Explicitly specify that run functions can be recursively re-entered.</p></blockquote>

<p>Accept the change.</p>

<h2>Discussion</h2>

<p>The [reentrancy] wording in the IS is underspecified
(see <a href="https://wg21.link/lwg2414">LWG 2414</a>)
but there are some uses of functions in the Networking TS
that should always work recursively, and some that definitely can't.
Instead of leaving it implementation-defined,
we can explicitly specify those cases.</p>

<h2>Proposed Wording</h2>

<p>Changes are relative to <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4656.pdf">N4656</a>.</p>

<p>Modify 13.2.2 [async.reqmts.executor] paragraph 4 as shown:</p>

<blockquote><p>The executor copy constructor, comparison operators, and other member functions defined in these requirements shall not introduce data races as a result of concurrent calls to those functions from different threads.
<ins> The member function <code>dispatch</code> may be recursively reentered. </ins></p></blockquote>

<p>Modify 13.7 [async.exec.ctx] as shown:</p>

<blockquote><p>-2-  Access to the services of an <code>execution_context</code> is via three function templates, <code>use_service<del>&lt;&gt;</del></code>, <code>make_service<del>&lt;&gt;</del></code> and <code>has_service<del>&lt;&gt;</del></code>.</p>

<p>-3- In a call to <code>use_service&lt;Service&gt;<del>()</del></code>, the type argument chooses a
service<ins>, identified by <code>Service::key_type</code>, from a set of services in an <code>execution_context</code></ins>.
If the service is not present in <del>an</del><ins>the</ins> <code>execution_context</code>, an object of type <code>Service</code> is created and added to the <code>execution_context</code>.
A program can check if an <code>execution_context</code> implements a particular service with the function template <code>has_service&lt;Service&gt;<del>()</del></code>.</p>

<p>-4- Service objects may be explicitly added to an <code>execution_context</code> using the function template <code>make_service&lt;Service&gt;<del>()</del></code>.
If the service is already present, <code>make_service</code> exits via an exception of type <code>service_already_exists</code>.</p>

<p>-5- Once a service reference is obtained from an <code>execution_context</code> object by calling <code>use_service<del>&lt;&gt;</del></code>, that
reference remains usable until a call to <code>destroy()</code>.</p></blockquote>

<p>Add a new paragraph to the end of 13.7 [async.exec.ctx]:</p>

<blockquote><p><ins> -6- If a call to a specialization of <code>use_service</code> or <code>make_service</code> recursively calls another specialization of <code>use_service</code> or <code>make_service</code> which would choose the same service (identified by <code>key_type</code>) from the same <code>execution_context</code>, then the behavior is undefined.
<em>[Note:</em> Nested calls to specializations for different service types are well-defined. <em>--end note]</em>
</ins></p></blockquote>

<p>Modify 13.7.5 [async.exec.ctx.globals]:</p>

<blockquote><p>-4- <del>Notes:</del> <ins><em>Remarks:</em></ins> The reference returned remains valid until a call to <code>destroy</code>.</p>

<p>[...]</p>

<p>-7- <del><em>Remarks:</em></del> <ins><em>Throws:</em></ins>
<code>service_already_exists</code> if a corresponding service object of type <code><del>Key</del><ins>Service::key_type</ins></code> is already present in the set.</p>

<p>-8- <del>Notes:</del> <ins><em>Remarks:</em></ins> The reference returned remains valid until a call to <code>destroy</code>.</p></blockquote>

<p>Modify 14.2 [io_context.io_context] paragraph 4 as shown:</p>

<blockquote><p>The <code>io_context</code> member functions <code>get_executor</code>, <code>stop</code>, and <code>stopped</code>, the run functions, and the <code>io_context::executor_type</code> copy constructors, member functions and comparison operators, do not introduce data races as a result of concurrent calls to those functions from different threads of execution. <em>[Note:</em> The <code>restart</code> member function is excluded from these thread safety requirements. <em>--end note]</em>
<ins> The run functions may be recursively reentered. </ins></p></blockquote>

<p>Remove 14.2.1 [io_context.io_context.members] paragraph 4 as shown:</p>

<blockquote><p><del> -4- <em>Requires:</em> Must not be called from a thread that is currently calling a run function. </del></p></blockquote>

<p>Under 14.2.1 [io_context.io_context.members] after paragraph 6 insert a new paragraph as shown:</p>

<blockquote><p><ins> -?- <em>[Note:</em> Calling <code>run</code> from a thread that is currently calling a run function may introduce the potential for deadlock. It is the caller's responsibility to avoid such deadlocks. <em>--end note]</em></p></blockquote>

<p>Remove 14.2.1 [io_context.io_context.members] paragraph 10 as shown:</p>

<blockquote><p><del> -10- <em>Requires:</em> Must not be called from a thread that is currently calling a run function.</p></blockquote>

<p>Under 14.2.1 [io_context.io_context.members] after paragraph 14 insert a new paragraph as shown:</p>

<blockquote><p><ins> -?- <em>[Note:</em> Calling <code>run_one</code> from a thread that is currently calling a run function may introduce the potential for deadlock. It is the caller's responsibility to avoid such deadlocks. <em>--end note]</em></p></blockquote>

<h2>Acknowledgments</h2>

<p>Thanks to Chris Kohlhoff for the wording for 016 (GB-7).</p>
</body></html>
