保证原子性的单比特操作

问题描述 投票:0回答:3

有没有办法在 C++ 中将单个位设置、清除、测试和翻转作为原子操作?例如“compare_and_swap”的按位变体。

c++ multithreading bit-manipulation atomic
3个回答
8
投票

以原子方式操作位需要

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
}

4
投票

翻转整数中的一位只是比较和交换操作。您使用它来测试和翻转单个位不会改变任何东西。所以一个简单的

compare_exchange_weak
循环就可以做到这一点。


3
投票

要原子地设置一点,请使用

std::atomic<int>::fetch_or(bit)
(也可使用
|=

要原子地清除一点,您可以使用

std::atomic<int>::fetch_and(~bit)
(也
&=

要原子翻转一点,您可以使用

std::atomic<int>::fetch_xor(bit)

© www.soinside.com 2019 - 2024. All rights reserved.