【发布时间】:2014-04-10 06:38:46
【问题描述】:
我想对一个 tbb 原子变量执行bitTestAndSet。
atomic.h from tbb似乎没有任何位操作。
如果我将 tbb 原子变量视为普通指针并执行__sync_or_and_fetch gcc 编译器不允许这样做。
有解决办法吗?
相关问题:
【问题讨论】:
我想对一个 tbb 原子变量执行bitTestAndSet。
atomic.h from tbb似乎没有任何位操作。
如果我将 tbb 原子变量视为普通指针并执行__sync_or_and_fetch gcc 编译器不允许这样做。
有解决办法吗?
相关问题:
【问题讨论】:
可以使用 compare_and_swap 循环,如下所示:
// Atomically perform i|=j. Return previous value of i.
int bitTestAndSet( tbb::atomic<int>& i, int j ) {
int o = i; // Atomic read (o = "old value")
while( (o|j)!=o ) { // Loop exits if another thread sets the bits
int k = o;
o = i.compare_and_swap(k|j,k);
if( o==k ) break; // Successful swap
}
return o;
}
请注意,如果 while 条件在第一次尝试时成功,则将只有一个获取栅栏,而不是完整栅栏。这是否重要取决于上下文。
如果存在高争用的风险,则应在循环中使用某种退避方案。 TBB 在内部使用类 atomic_backoff 进行争用管理,但它目前不是公共 TBB API 的一部分。
还有第二种方法,如果不关心可移植性并且您愿意利用未记录的事实,即 tbb::atomic 和 T 的布局在 x86 平台上是相同的。在这种情况下,只需使用汇编代码对 tbb::atomic 进行操作。下面的程序演示了这种技术:
#include <tbb/tbb.h>
#include <cstdio>
inline int SetBit(int array[], int bit) {
int x=1, y=0;
asm("bts %2,%0\ncmovc %3,%1" : "+m" (*array), "+r"(y) : "r" (bit), "r"(x));
return y;
}
tbb::atomic<int> Flags;
volatile int Result;
int main() {
for( int i=0; i<16; ++i ) {
int k = i*i%32;
std::printf("bit at %2d was %d. Flags=%8x\n", k, SetBit((int*)&Flags,k), +Flags);
}
}
【讨论】:
cmpxchg吗?