具有保证原子性的单位操作

Dan*_*per 1 c++ multithreading bit-manipulation atomic

有没有办法在c ++中设置,清除,测试和翻转单个位作为原子操作?例如"compare_and_swap"的按位变体.

Dav*_*rtz 5

在整数中翻转只是比较和交换操作.你用它来测试和翻转一个位不会改变任何东西.所以一个简单的compare_exchange_weak循环会做到这一点.


LWi*_*sey 5

原子地操作位需要compare_exchangeRMW以避免触摸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
}
Run Code Online (Sandbox Code Playgroud)

  • @morty如果“compare_exchange_weak”返回 false,它将用当前值更新其第一个参数。因此,第一个参数(“val”)必须是左值引用。 (2认同)
  • 为什么不使用 fetch_or、fetch_and 或 fetch_xor ? (2认同)