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_id是std::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().
这在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)
| 归档时间: |
|
| 查看次数: |
756 次 |
| 最近记录: |