2013-02-13 206 views
1

我目前有麻烦正确理解新的std::atomic类型的用法。对于我来说,我有以下假设:C++ 11 std :: atomic_fetch_add vs __sync_fetch_and_add

  1. 我存储在内存中
  2. 我有两种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,想知道我应该如何处理这个科尔ectly。根据我对std::atomic_fetch_add的理解,基本上需要一个原子积分值来做到这一点。然而,我需要如何正确实现这一点,以便我可以将一个原子变量指向一个位置并递增该值?

谢谢!

+0

你可能对你的问题更精确一点吗?你可以像普通的int那样对待一个'std :: atomic',甚至操作符对于正常的使用情况都是重载的。 – inf 2013-02-13 17:21:44

+0

我有点困惑,你想_data是一个正常的uint64和pos是原子变量或两者都是原子?我在这里举了一个简单的例子http://ideone.com/7RqlwP。正如bamboon所说的,你可以正常和原子地增加原子变量。 – 2013-02-13 17:36:45

+0

你必须跳过额外的箍来获得非原子增量。重载运算符等价于相应的'atomic_fetch_ * op *'调用 – JoergB 2013-02-13 17:59:08

回答

3

你不能。

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

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

做你想做的事还是什么需要特定于平台的功能。

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

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

这仍然会做原子负载和存储,但没有记忆围栏或原子读 - 修改 - 写操作。

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]++