Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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();
like image 627
vpozdyayev Avatar asked Oct 03 '12 07:10

vpozdyayev


1 Answers

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

like image 101
Anthony Williams Avatar answered Sep 21 '22 21:09

Anthony Williams