c++ - 在 tbb 原子变量上进行位测试和设置 (BTS)

标签 c++ c assembly tbb

我想对 tbb 原子变量执行 bitTestAndSet

atomic.h from tbb好像没有任何位操作。

如果我将 tbb 原子变量视为普通指针并执行 __sync_or_and_fetch gcc 编译器不允许这样做。

有解决办法吗?

相关问题:

assembly intrinsic for bit test and set (BTS)

最佳答案

可以使用 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 进行竞争管理,但它目前不是公共(public) 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);
    }
}

关于c++ - 在 tbb 原子变量上进行位测试和设置 (BTS),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22980352/

相关文章:

c - 读取整数

c - 从命令行从 C 文件中读取输入测试用例

c++ - 在引用函数中使用的参数 c++

c++ - 运行快速修复引擎

java - 如何用语言对 OSI 引用模型进行编程

c - Linux下实现窗口函数InterlockedExchange

assembly - 如何在 8080 上高效地进行签名比较?

assembly - 影子寄存器——arm

c++ - Valgrind 和 QEMU - 无法检测内存泄漏

c++ - 在 mac os x (10.8) 中链接