This page is a snapshot from the LWG issues list, see the Library Active Issues List for more information and the meaning of NAD status.

### 1485. Unclear `thread::id` specification

Section: 32.4.3.2 [thread.thread.id] Status: NAD Submitter: INCITS Opened: 2010-08-25 Last modified: 2016-01-28

Priority: Not Prioritized

View all other issues in [thread.thread.id].

View all issues with NAD status.

Discussion:

Addresses US-184

It is unclear when a `thread::id` ceases to be meaningful. The sentence "The library may reuse the value of a `thread::id` of a terminated thread that can no longer be joined." implies that some terminated threads can be joined. It says nothing about detached threads.

[ Resolution proposed by ballot comment: ]

> Require a unique `thread::id` for every thread that is (1) detached and not terminated or (2) has an associated `std::thread` object.

[ 2010-11-22 Howard Hinnant observes ]

A thread can either be running or terminated. Additionally a thread can be joined, detached, or neither. These combine into the five possible states shown in this table:

| Running | Terminated
--- | --- | ---
Neither joined nor detached | shall not reuse id | shall not reuse id
detached | shall not reuse id | may reuse id
joined | impossible state | may reuse id

Only if a thread is neither joined nor detached can it be joined. Or said differently, if a thread has already been joined or detached, then it can not be joined. The sentence:

> The library may reuse the value of a `thread::id` of a terminated thread that can no longer be joined.

precisely defines the two states shown in the above table where a thread::id may be reused.

The following program illustrates all of the possibilities:

>     #include <mutex>
>     #include <thread>
>     #include <iostream>
>     #include <chrono>

>     std::mutex mut;

>     void f()
>     {
>        std::lock_guard<std::mutex> _(mut);
>        std::cout << "f id = " << std::this_thread::get_id() << " terminating\n";
>     }

>     void g()
>     {
>        std::lock_guard<std::mutex> _(mut);
>        std::cout << "g id = " << std::this_thread::get_id() << " terminating\n";
>     }

>     int main()
>     {
>        std::cout << "main id = " << std::this_thread::get_id() << "\n";
>        std::thread t1(f);
>        std::thread(g).detach();
>        std::this_thread::sleep_for(std::chrono::seconds(1));
>        std::cout << "g's thread::id can be reused here because g has terminated and is detached.\n";
>        std::cout << "f's thread::id can't be reused here because f has terminated but is still joinable.\n";
>        std::cout << "f id = " << t1.get_id() << "\n";
>        t1.join();
>        std::cout << "f's thread::id can be reused here because f has terminated and is joined.\n";
>        std::cout << "f id = " << t1.get_id() << "\n";
>     }

>     main id = 0x7fff71197ca0
>     f id = 0x100381000 terminating
>     g id = 0x100581000 terminating
>     g's thread::id can be reused here because g has terminated and is detached.
>     f's thread::id can't be reused here because f has terminated but is still joinable.
>     f id = 0x100381000
>     f's thread::id can be reused here because f has terminated and is joined.
>     f id = 0x0

[2011-02-11 Reflector discussion]

Moved to Tentatively NAD after 5 votes.

Proposed resolution: