2017-06-26 30 views
1

有沒有一種方法可以在C++中設置,清除,測試和翻轉單個位作爲原子操作?例如按位變量來「compare_and_swap」。具有保證原子性的單位操作

+0

'的std :: atomic_bool'? – erip

+3

沒有「C/C++」。選一個*。 –

+0

你在使用什麼架構?如果給定的體系結構不支持位級原子操作,那麼語言/編譯器不會神奇地使它成爲可能。 –

回答

3

在整數中翻轉一點只是比較和交換操作。你用它來測試和翻轉一個位不會改變任何東西。所以一個簡單的compare_exchange_weak循環會做到這一點。

+0

時,檢出std :: bitset假定您知道預期的結果。位操作中不是這種情況。 – chook

+1

請注意,C/C++「原子」與不可中斷意義上的原子操作不同,它只是保證了一定程度的線程安全。例如,stdatomic.h不適用於ISR可中斷的內核代碼。見https://stackoverflow.com/questions/19900524/does-the-c-11-standard-guarantees-that-stdatomic-is-implemented-as-an-atom –

+0

@chook你不能先讀一下確定預期的結果? – xaxxon

3

原子操作位需要一個compare_exchange RMW以避免觸及atomic變量中的其他位。 測試一點不是一個修改操作,因此一個load()就足夠了。

您必須添加範圍錯誤檢查

template<typename T, typename OP> 
T manipulate_bit(std::atomic<T> &a, unsigned n, OP bit_op) 
{ 
    static_assert(std::is_integral<T>::value, "atomic type not integral"); 

    T val = a.load(); 
    while (!a.compare_exchange_weak(val, bit_op(val, n))); 

    return val; 
} 

auto set_bit = [](auto val, unsigned n) { return val | (1 << n); }; 
auto clr_bit = [](auto val, unsigned n) { return val & ~(1 << n); }; 
auto tgl_bit = [](auto val, unsigned n) { return val^(1 << n); }; 


int main() 
{ 
    std::atomic<int> a{0x2216}; 

    manipulate_bit(a, 3, set_bit); // set bit 3 

    manipulate_bit(a, 7, tgl_bit); // toggle bit 7 

    manipulate_bit(a, 13, clr_bit); // clear bit 13 

    bool isset = (a.load() >> 5) & 1; // testing bit 5 
} 
+0

好;我會'返回val;',因爲知道你從過渡到常常是有用的。 – Yakk

+0

同意;它實際上更接近於原子操作遵循的設計慣例 – LWimsey