3

私は現在、新しいstd::atomic型の使用法を正しく理解するのに苦労しています。私の場合、次の仮定があります。

  1. uint64_tメモリに格納された値の連続したメモリ位置があります
  2. 単純なインクリメントとアトミックインクリメントの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_tの配列を の配列に置き換える必要がありますstd::atomic<uint64_t>。多くのプラットフォームでは、これは plain と同じサイズと配置になりuint64_tますが、すべての操作はアトミックになります。

data[pos].fetch_add(1,memory_order)その後、指定された でアトミック インクリメントを実行するために使用できますmemory_orderstd::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 に答える