std :: thread :: id的要求.可以雾化吗?

vpo*_*yev 8 c++ multithreading atomic language-lawyer c++11

标准说:"thread :: id类型的对象为所有不代表执行线程的线程对象提供了一个不同的值".这是单个/不同的值operator==,或者它是实际的按位单/不同值?

问题的原因:MSVC2012 std::thread::id::id()在其中一个字段中留下了垃圾,并且它打破了对比较交换的代码std::atomic<std::thread::id>(因为后者依赖于按位比较).

首先是std::atomic<std::thread::id>法律结构吗?

编辑:作为参考,代码如下:

while( !worker_id.compare_exchange_weak( no_id = thread_id_type(), self_id ) )
    sleep();
Run Code Online (Sandbox Code Playgroud)

Ant*_*ams 10

首先,std::atomic<std::thread::id>是合法的:std::thread::id要求是可以轻易复制的(30.3.1.1p2),它符合std::atomic<>(29.5p1)的要求.

但是,它是一个不透明的类,因此不要求比较相等的对象的位模式是相同的.

因此,如果您使用compare_exchange_weak或者compare_exchange_strong它可能会失败的比较相等的值.

因此,建议是compare_exchange_weak在循环中使用,expected值保留为前一次迭代的结果.

在你的情况下,我从你的循环中解释的语义是:keep looping while是worker_id另一个线程的ID,或者worker_idstd::thread::id但是交换失败了.您可以通过以下方式实现此目的:

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();
}
Run Code Online (Sandbox Code Playgroud)

要么

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();
Run Code Online (Sandbox Code Playgroud)

即只改变no_id,如果是价值 std::thread::id().


cme*_*erw 5

这在LWG924中进行了讨论.基本上,你不能使用compare_exchange_strong,但你应该能够在循环中使用compare_exchange_weak,例如

expected = current.load();
do {
  desired = function(expected);
} while (!current.compare_exchange_weak(expected, desired));
Run Code Online (Sandbox Code Playgroud)

编辑:无条件地重置值会破坏循环的目的 - 基于提供的代码,我认为最好的解决方案是:

no_id = std::thread::id();
while( !worker_id.compare_exchange_weak( no_id, self_id ) )
{
  if (no_id != std::thread::id())
  {
    sleep();
    no_id = std::thread::id();
  }
}
Run Code Online (Sandbox Code Playgroud)