This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of New status.
std::thread
's constructor needs to be able to report general memory allocation failuresSection: 32.4.3.3 [thread.thread.constr], 32.4.4.2 [thread.jthread.cons] Status: New Submitter: Billy O'Neal III Opened: 2020-08-14 Last modified: 2020-09-06
Priority: 3
View all other issues in [thread.thread.constr].
View all issues with New status.
Discussion:
(j)thread
's constructor needs to decay-copy
the supplied parameters and callable over to the started
thread through an operating system API that generally only accepts a single void*
. The MSVC++ and libc++
implementations do this by putting the parameters in a std::tuple
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.
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.
It is technically possible to implement the current design by transforming this allocation failure into
resource_unavailable_try_again
, 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.
[2020-08-21; Issue processing telecon: set priority to 3]
Jonathan: I prefer Option A, but I think we need something like:
"any exceptions thrown by the decay-copy
calls, or ...".
Proposed resolution:
This wording is relative to N4861.
[Drafting Note: Two mutually exclusive options are prepared, depicted below by Option A and Option B, respectively.]
Option A: The memory allocation failure results in bad_alloc
.
Modify 32.4.3.3 [thread.thread.constr] as indicated:
template<class F, class... Args> explicit thread(F&& f, Args&&... args);-3- Constraints: […]
[…]
-8- Postconditions:
get_id() != id()
.*this
represents the newly started thread.-9- Throws:
bad_alloc
if memory to transfer parameters to the new thread cannot be obtained.system_error
if unable to start the new thread.-10- Error conditions:
(10.1) —
resource_unavailable_try_again
— 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.
Modify 32.4.4.2 [thread.jthread.cons] as indicated:
template<class F, class... Args> explicit jthread(F&& f, Args&&... args);-3- Constraints: […]
[…]
-8- Postconditions:
get_id() != id()
istrue
andssource.stop_possible()
istrue
and*this
represents the newly started thread. [Note: The calling thread can make a stop request only once, because it cannot replace this stop token. — end note]-9- Throws:
bad_alloc
if memory to transfer parameters to the new thread cannot be obtained.system_error
if unable to start the new thread.-10- Error conditions:
(10.1) —
resource_unavailable_try_again
— 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.
Option B: The memory allocation failure results in a system_error
with the error condition
out_of_memory
.
Modify 32.4.3.3 [thread.thread.constr] as indicated:
template<class F, class... Args> explicit thread(F&& f, Args&&... args);-3- Constraints: […]
[…]
-8- Postconditions:
get_id() != id()
.*this
represents the newly started thread.-9- Throws:
system_error
if unable to start the new thread.-10- Error conditions:
(10.?) —
not_enough_memory
— the system lacked memory resources to transfer parameters to the new thread.(10.1) —
resource_unavailable_try_again
— 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.
Modify 32.4.4.2 [thread.jthread.cons] as indicated:
template<class F, class... Args> explicit jthread(F&& f, Args&&... args);-3- Constraints: […]
[…]
-8- Postconditions:
get_id() != id()
istrue
andssource.stop_possible()
istrue
and*this
represents the newly started thread. [Note: The calling thread can make a stop request only once, because it cannot replace this stop token. — end note]-9- Throws:
system_error
if unable to start the new thread.-10- Error conditions:
(10.?) —
not_enough_memory
— the system lacked memory resources to transfer parameters to the new thread.(10.1) —
resource_unavailable_try_again
— 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.