在TBB原子变量位测试和设置(BTS) [英] bit test and set (BTS) on a tbb atomic variable
问题描述
我想要做的 bitTestAndSet
在TBB原子变量。
I want to do bitTestAndSet
on a tbb atomic variable.
atomic.h中从TBB 似乎并不具备任何位操作。
atomic.h from tbb does not seem to have any bit operations.
如果我对待TBB原子变量作为一个正常的指针,并做 __ sync_or_and_fetch
gcc编译器不允许。
If I treat the tbb atomic variable as a normal pointer and do __sync_or_and_fetch
gcc compiler doesn't allow that.
有没有解决方法呢?
相关问题:
<一个href=\"http://stackoverflow.com/questions/22974382/assembly-intrinsic-for-bit-test-and-set-bts\">assembly内在的位测试和设置(BTS)
推荐答案
一个compare_and_swap循环可以使用,这样的:
A compare_and_swap loop can be used, like this:
// 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条件成功,将有只获取栅栏,不是一个完整的围墙。无论是重要的取决于上下文。
Note that if the while condition succeeds on the first try, there will be only an acquire fence, not a full fence. Whether that matters depends on context.
如果有高争的危险,那么某种形式的补偿方案应该是在循环使用。 TBB使用争管理类atomic_backoff内部,但它不是目前大众TBB API的一部分。
If there is risk of high contention, then some sort of backoff scheme should be be used in the loop. TBB uses a class atomic_backoff for contention management internally, but it's not currently part of the public TBB API.
还有第二个办法,如果便携性是不是一个问题,你是愿意利用未公开的事实,TBB ::原子和T的布局是在x86平台上是相同的。在这种情况下,只是在操作TBB原子::使用汇编code。下面的程序演示了这种方法:
There is a second way, if portability is not a concern and you are willing to exploit the undocumented fact that the layout of a tbb::atomic and T are the same on x86 platforms. In that case, just operate on the tbb::atomic using assembly code. The program below demonstrates this technique:
#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);
}
}
这篇关于在TBB原子变量位测试和设置(BTS)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!