我目前正在正确理解新std::atomic
类型的用法。对于我的情况,我有以下假设:
uint64_t
值的连续内存位置最初我实现了像这样的方法
uint64_t inc(const size_t pos) { return _data[pos]++; }
uint64_t atomic_inc(const size_t pos) { return __sync_fetch_and_add(&_data[pos], 1); }
现在我想把它正确地移植到C ++ 11,并且想知道我该如何正确处理它。从我对std::atomic_fetch_add的理解,基本上需要一个原子积分值才能做到这一点。但是,我如何正确地实现这一点,以便我可以使用原子变量指向某个位置并增加该值?
谢谢!
答案 0 :(得分:7)
您不能使用C ++ 11工具来获取未声明为原子类型的变量的原子访问。您需要将uint64_t
数组替换为std::atomic<uint64_t>
数组。在许多平台上,它将具有与普通uint64_t
相同的大小和对齐方式,但所有操作都将是原子操作。
然后,您可以使用data[pos].fetch_add(1,memory_order)
使用指定的memory_order
进行原子增量。如果您需要std::memory_order_seq_cst
的内存顺序(可能最接近GCC __sync_fetch_and_add
),则可以省略内存顺序,或者可以使用增量运算符,例如: data[pos]++
。
答案 1 :(得分:3)
你不能。
C ++ 11原子对象封装了它的基类型。它不提供对lvalue的值的访问,也不能将其设置为对基础类型的预先存在的对象(在给定的内存位置)提供原子操作。
根据平台的不同,任何给定的原子类型可能都有特殊要求(例如更强的对齐约束)或需要辅助数据(大多数原子类型都不能保证无锁)
执行您想要做的事情仍然需要特定于平台的功能。
如果您想进行非原子增量,最接近的是:
atomic<uint64_t> data(initial_value);
data.store(data.load(memory_order_relaxed) + 1, memory_order_relaxed);
这仍将执行原子加载和存储,但不进行内存屏蔽或原子读取 - 修改 - 写入操作。