<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Issue 3475: std::thread's constructor needs to be able to report general memory allocation failures</title>
<meta property="og:title" content="Issue 3475: std::thread's constructor needs to be able to report general memory allocation failures">
<meta property="og:description" content="C++ library issue. Status: New">
<meta property="og:url" content="https://cplusplus.github.io/LWG/issue3475.html">
<meta property="og:type" content="website">
<meta property="og:image" content="http://cplusplus.github.io/LWG/images/cpp_logo.png">
<meta property="og:image:alt" content="C++ logo">
<style>
  p {text-align:justify}
  li {text-align:justify}
  pre code.backtick::before { content: "`" }
  pre code.backtick::after { content: "`" }
  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.issues-index { border: 1px solid; border-collapse: collapse; }
  table.issues-index th { text-align: center; padding: 4px; border: 1px solid; }
  table.issues-index td { padding: 4px; border: 1px solid; }
  table.issues-index td:nth-child(1) { text-align: right; }
  table.issues-index td:nth-child(2) { text-align: left; }
  table.issues-index td:nth-child(3) { text-align: left; }
  table.issues-index td:nth-child(4) { text-align: left; }
  table.issues-index td:nth-child(5) { text-align: center; }
  table.issues-index td:nth-child(6) { text-align: center; }
  table.issues-index td:nth-child(7) { text-align: left; }
  table.issues-index td:nth-child(5) span.no-pr { color: red; }
  @media (prefers-color-scheme: dark) {
     html {
        color: #ddd;
        background-color: black;
     }
     ins {
        background-color: #225522
     }
     del {
        background-color: #662222
     }
     a {
        color: #6af
     }
     a:visited {
        color: #6af
     }
     blockquote.note
     {
        background-color: rgba(255, 255, 255, .10)
     }
  }
</style>
</head>
<body>
<hr>
<p><em>This page is a snapshot from the LWG issues list, see the <a href="lwg-active.html">Library Active Issues List</a> for more information and the meaning of <a href="lwg-active.html#New">New</a> status.</em></p>
<h3 id="3475"><a href="lwg-active.html#3475">3475</a>. <code>std::thread</code>'s constructor needs to be able to report general memory allocation failures</h3>
<p><b>Section:</b> 32.4.3.3 <a href="https://wg21.link/thread.thread.constr">[thread.thread.constr]</a>, 32.4.4.2 <a href="https://wg21.link/thread.jthread.cons">[thread.jthread.cons]</a> <b>Status:</b> <a href="lwg-active.html#New">New</a>
 <b>Submitter:</b> Billy O'Neal III <b>Opened:</b> 2020-08-14 <b>Last modified:</b> 2020-09-06</p>
<p><b>Priority: </b>3
</p>
<p><b>View other</b> <a href="lwg-index-open.html#thread.thread.constr">active issues</a> in [thread.thread.constr].</p>
<p><b>View all other</b> <a href="lwg-index.html#thread.thread.constr">issues</a> in [thread.thread.constr].</p>
<p><b>View all issues with</b> <a href="lwg-status.html#New">New</a> status.</p>
<p><b>Discussion:</b></p>
<p>
<code>(j)thread</code>'s constructor needs to <code><i>decay-copy</i></code> the supplied parameters and callable over to the started 
thread through an operating system API that generally only accepts a single <code>void*</code>. The MSVC++ and libc++ 
implementations do this by putting the parameters in a <code>std::tuple</code> allocated from the heap, passing a 
pointer to that tuple through the operating system API, and leaving ownership of the parameters to the other thread.
<p/>
It might be theoretically possible to introduce an additional copy and synchronization where the starting thread 
blocks for the started thread to make a move constructed copy of that tuple from the parameters, but that would 
introduce unreasonable synchronization overhead since the starting thread would have to block for all TLS 
initializers and similar in the started thread.
<p/>
It is technically possible to implement the current design by transforming this allocation failure into 
<code>resource_unavailable_try_again</code>, but the description for this error in the standard is that some thread-based 
limitation has been reached, not a general memory limit, so that doesn't seem to meet the spirit of the requirement.
</p>
<p><i>[2020-08-21; Issue processing telecon: set priority to 3]</i></p>

<p>
Jonathan: I prefer Option A, but I think we need something like:
"any exceptions thrown by the <i><code>decay-copy</code></i> calls, or ...".
</p>


<p id="res-3475"><b>Proposed resolution:</b></p>
<p>
This wording is relative to <a href="https://wg21.link/n4861">N4861</a>.
</p>

<blockquote class="note">
<p>
[<i>Drafting Note:</i> Two mutually exclusive options are prepared, depicted below by <b>Option A</b> and 
<b>Option B</b>, respectively.] 
</p>
</blockquote>

<p>
<b>Option A:</b> The memory allocation failure results in <code>bad_alloc</code>.
</p>
<ol>
<li><p>Modify 32.4.3.3 <a href="https://wg21.link/thread.thread.constr">[thread.thread.constr]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class F, class... Args&gt; explicit thread(F&amp;&amp; f, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> [&hellip;]
<p/>
[&hellip;]
<p/>
-8- <i>Postconditions:</i> <code>get_id() != id()</code>. <code>*this</code> represents the newly started thread.
<p/>
-9- <i>Throws:</i> <ins><code>bad_alloc</code> if memory to transfer parameters to the new thread cannot be obtained.</ins> 
<code>system_error</code> if unable to start the new thread.
<p/>
-10- <i>Error conditions:</i>
</p>
<ol style="list-style-type: none">
<li><p>(10.1) &mdash; <code>resource_unavailable_try_again</code> &mdash; the system lacked the necessary resources 
to create another thread, or the system-imposed limit on the number of threads in a process would be exceeded.</p></li>
</ol>
</blockquote>
</blockquote>
</li>

<li><p>Modify 32.4.4.2 <a href="https://wg21.link/thread.jthread.cons">[thread.jthread.cons]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class F, class... Args&gt; explicit jthread(F&amp;&amp; f, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> [&hellip;]
<p/>
[&hellip;]
<p/>
-8- <i>Postconditions:</i> <code>get_id() != id()</code> is <code>true</code> and <code>ssource.stop_possible()</code> 
is <code>true</code> and <code>*this</code> represents the newly started thread. [<i>Note:</i> The calling thread 
can make a stop request only once, because it cannot replace this stop token. &mdash; <i>end note</i>]
<p/>
-9- <i>Throws:</i> <ins><code>bad_alloc</code> if memory to transfer parameters to the new thread cannot be obtained.</ins> 
<code>system_error</code> if unable to start the new thread.
<p/>
-10- <i>Error conditions:</i>
</p>
<ol style="list-style-type: none">
<li><p>(10.1) &mdash; <code>resource_unavailable_try_again</code> &mdash; the system lacked the necessary resources 
to create another thread, or the system-imposed limit on the number of threads in a process would be exceeded.</p></li>
</ol>
</blockquote>
</blockquote>
</li>

</ol>

<p>
<b>Option B:</b> The memory allocation failure results in a <code>system_error</code> with the error condition 
<code>out_of_memory</code>.
</p>
<ol>
<li><p>Modify 32.4.3.3 <a href="https://wg21.link/thread.thread.constr">[thread.thread.constr]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class F, class... Args&gt; explicit thread(F&amp;&amp; f, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> [&hellip;]
<p/>
[&hellip;]
<p/>
-8- <i>Postconditions:</i> <code>get_id() != id()</code>. <code>*this</code> represents the newly started thread.
<p/>
-9- <i>Throws:</i> <code>system_error</code> if unable to start the new thread.
<p/>
-10- <i>Error conditions:</i>
</p>
<ol style="list-style-type: none">
<li><p><ins>(10.?) &mdash; <code>not_enough_memory</code> &mdash; the system lacked memory resources to transfer parameters 
to the new thread.</ins></p></li>
<li><p>(10.1) &mdash; <code>resource_unavailable_try_again</code> &mdash; the system lacked the necessary resources 
to create another thread, or the system-imposed limit on the number of threads in a process would be exceeded.</p></li>
</ol>
</blockquote>
</blockquote>
</li>

<li><p>Modify 32.4.4.2 <a href="https://wg21.link/thread.jthread.cons">[thread.jthread.cons]</a> as indicated:</p>

<blockquote>
<pre>
template&lt;class F, class... Args&gt; explicit jthread(F&amp;&amp; f, Args&amp;&amp;... args);
</pre>
<blockquote>
<p>
-3- <i>Constraints:</i> [&hellip;]
<p/>
[&hellip;]
<p/>
-8- <i>Postconditions:</i> <code>get_id() != id()</code> is <code>true</code> and <code>ssource.stop_possible()</code> 
is <code>true</code> and <code>*this</code> represents the newly started thread. [<i>Note:</i> The calling thread 
can make a stop request only once, because it cannot replace this stop token. &mdash; <i>end note</i>]
<p/>
-9- <i>Throws:</i> <code>system_error</code> if unable to start the new thread.
<p/>
-10- <i>Error conditions:</i>
</p>
<ol style="list-style-type: none">
<li><p><ins>(10.?) &mdash; <code>not_enough_memory</code> &mdash; the system lacked memory resources to transfer parameters 
to the new thread.</ins></p></li>
<li><p>(10.1) &mdash; <code>resource_unavailable_try_again</code> &mdash; the system lacked the necessary resources 
to create another thread, or the system-imposed limit on the number of threads in a process would be exceeded.</p></li>
</ol>
</blockquote>
</blockquote>
</li>

</ol>





</body>
</html>
