2014-04-10 26 views

回答

2

一個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; 
} 

注意,如果在第一次嘗試時狀態成功,將只有一個獲得圍欄,而不是一個完整的圍欄。是否重要取決於上下文。

如果存在高爭用風險,則應該在循環中使用某種退避方案。 TBB在內部爲爭用管理使用類atomic_backoff,但它目前不是公共TBB API的一部分。

還有第二種方法,如果可移植性不是問題,並且您願意利用x86平臺上tbb :: atomic和T的佈局相同的無證事實。在這種情況下,只需使用匯編代碼對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); 
    } 
} 
+0

感謝您的回答。我不希望位設置失敗。如果我使用CAS,它可能無法設置該位。我想盲目設置位 – arunmoezhi

+0

如果位集失敗並重試,它有什麼不同?這就好像線程稍後到達一樣。並非所有的硬件都具有原子比特集。事實上,如果使用sync_or_and_fetch的結果,gcc會生成一個cmpxchg循環。我假設結果是有趣的,因爲問題標題是「測試和設置」,而不僅僅是「設置」。 –

+0

如果機器有硬件BTS指令,那麼它會使用'cmpxchg'嗎? – arunmoezhi