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();
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()
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With