3

我目前无法正确理解新std::atomic类型的用法。对于我的情况,我有以下假设:

  1. 我有一个uint64_t存储在内存中的值的连续内存位置
  2. 我有两种访问简单增量和原子增量

最初我实现了这样的方法

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的理解,基本上需要一个原子整数值来执行此操作。但是,我需要如何正确实现这一点,以便我可以使用原子变量指向一个位置并增加值?

谢谢!

4

2 回答 2

9

您不能使用 C++11 工具对未声明为原子类型的变量进行原子访问。您需要将数组替换uint64_tstd::atomic<uint64_t>. 在许多平台上,这将具有与 plain 相同的大小和对齐方式uint64_t,但所有操作都是原子的。

然后,您可以使用data[pos].fetch_add(1,memory_order)指定的memory_order. 如果您需要的内存顺序std::memory_order_seq_cst(这可能是最接近 GCC 的__sync_fetch_and_add),那么可以省略内存顺序,或者您可以使用增量运算符,例如data[pos]++.

于 2013-02-13T22:12:57.427 回答
3

你不能。

C++11 原子对象封装了它的基类型。它不提供对其值作为左值的访问,也不能将其设置为对基础类型的预先存在的对象(在给定的内存位置)提供原子操作。

根据平台,任何给定的原子类型可能有特殊要求(例如更强的对齐约束)或需要辅助数据(大多数原子类型不保证是无锁的)

做你想做的事仍然需要特定于平台的功能。

如果你想做非原子增量,你能得到的最接近的是:

  atomic<uint64_t> data(initial_value);
  data.store(data.load(memory_order_relaxed) + 1, memory_order_relaxed);

这仍然会执行原子加载和存储,但不会执行内存隔离或原子读取-修改-写入操作。

于 2013-02-13T17:48:55.230 回答