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.

### 3475. `std::thread`'s constructor needs to be able to report general memory allocation failures

Section: 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`.

1. 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:

   > > 1. (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.

2. 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()` is `true` and `ssource.stop_possible()` is `true` 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:

   > > 1. (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`.

1. 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:

   > > 1. (10.?) — `not_enough_memory` — the system lacked memory resources to transfer parameters to the new thread.

   > > 2. (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.

2. 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()` is `true` and `ssource.stop_possible()` is `true` 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:

   > > 1. (10.?) — `not_enough_memory` — the system lacked memory resources to transfer parameters to the new thread.

   > > 2. (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.