Requirements for std::thread::id. Can it be atomized?

atomic, c++, c++11, language-lawyer, multithreading

Solution

Firstly, `std::atomic<std::thread::id>` is legal: `std::thread::id` is required to be trivially copyable (30.3.1.1p2), which meets the requirements of `std::atomic<>` (29.5p1).

However, it is an opaque class, so there is no requirement that the bit pattern of objects that compare equal be identical.

Consequently, if you use `compare_exchange_weak` or `compare_exchange_strong` then it may fail for values that compare equal.

Thus, the advice is to use `compare_exchange_weak` in a loop, leaving the `expected` value as the result of the previous iteration.

In your case, the semantics I interpret from your loop are: keep looping whilst `worker_id` is the ID of another thread, or `worker_id` was `std::thread::id` but the exchange failed. You can achieve this with the following:

no_id=std::thread::id();
while((no_id!=std::thread::id()) ||
      !worker_id.compare_exchange_weak( no_id, self_id ) ){
    if(no_id!=std::thread::id()) no_id=std::thread::id();
    sleep();
}

or

no_id=std::thread::id();
while(!worker_id.compare_exchange_weak(
          (no_id!=std::thread::id())?(no_id=std::thread::id())?no_id, self_id ) )
    sleep();

i.e. only change the `no_id` value if it is not `std::thread::id()`.

Problem

The standard says: "An object of type thread::id provides... a single distinct value for all thread objects that do not represent a thread of execution". Is that a single/distinct value with regard to `operator==`, or is it the actual bitwise-single/distinct value? The reason for the question: MSVC2012's `std::thread::id::id()` leaves garbage in one of its fields, and it breaks code that does compare-exchange on an `std::atomic<std::thread::id>` (since the latter depends on bitwise comparisons). Is `std::atomic<std::thread::id>` a legal construct in the first place? EDIT: for the reference, the code goes like this: ``` while( !worker_id.compare_exchange_weak( no_id = thread_id_type(), self_id ) ) sleep(); ```

Original source