2013-02-13 205 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]++