2012-11-15 10 views
9

一部のWindows C++コードをiOSに移植する際に、Win32のlong InterlockedIncrement(long *p)呼び出しの実装を提供する必要があります。これは、<libkern/OSAtomic.h>で定義されている関数を使用すれば十分です。C++ 11 <atomic>を使用して整数へのポインタのアトミックなインクリメントを実装する方法は?

しかし、C++ 11の機能(主に<atomic>)を使用してOSに依存しない方法で書くことができるかどうかは疑問です。

inline long InterlockedIncrement(long* p) 
{ 
    std::atomic<long&> atomicP(*p); 
    return ++atomicP; 
} 

は、この作業を行います:私は、私はわからないこれは私が欲しいものを達成し、これを思いつきましたか?それで十分ですか? 2つの行はアトミックではありませんが、インクリメントはアトミックでなければなりません。

私が見つけた<atomic>の使用例はすべて異なります。std::atomic<T>が定義され、直接使用されています。ここでは、発信者がアドレスで私に渡す既存の長い変数を使用したいと思います。私はそのような例を見つけることができませんでした。

編集:クラン3.2(Xcodeの4.xのは、)(どちらかでもatomicP += 1)エラー「タイプstd::atomic<long&>の値をインクリメントすることはできません」と++atomicPのコンパイルに失敗しました。

正しい方法は何ですか?

編集再び:、ポインタの実装は...

inline long InterlockedIncrement(long* p) 
{ 
    std::atomic<long*> atomicP(p); 
    return ++(*atomicP); 
} 

をコンパイルしかし、私は、原子の種類が、ポインタが指す値をインクリメントしていないので、私は、これは動作しません怖いですこれは原子ではない。

+0

私はあなたが 'アトミック'を持つことはできないと思います。ポインタのバージョンが間違っています(格納されているポインタ自体は、指し示された値ではなく、アトミックになります)。 – interjay

+0

いいえ、これは実装固有のものなしではまったく動作しません。 –

+2

ポートの 'std :: atomic 'に変換するのは時間でしょうか? WindowsとOSXでは 'long 'のサイズが異なることを考慮すると、おそらく何らかのOS固有の処理を行わなければならないでしょう。 –

答えて

10

あなたのサンプル実装では、毎回ポインタから新しいアトミックを構築しています。これはstd :: atomicの意図された使用ではなく、私はそれがあなたが好きなように動作するとは思わない。

私が知っている限り、あなたが探していることを実行する唯一の方法(プラットフォームに依存しない方法でInterlockedIncrementへの依存を取り除く)は、現在Win32の "interlock"呼び出しを呼び出す変数の宣言をstd ::それらの原子バージョン。次に、インターロックされた呼び出しを削除し、通常の値セマンティクスを使用して、変数をアトミックに変更できます。これは、とにかくもっと読みやすく(将来的にはより保守的です)。

既存の(よくテストされた)コードをそのまま残しておきたいと思っていますが、私はあなたのケースではできないと思います。

+2

私はそれを恐れていました。あなたは私の状況を正しく要約しました。あなたの評価に感謝します。 –

1

atomic_fetch_add操作を使用できると思います。例hereを見てください。

+2

これには、既存の 'std :: atomic'変数が必要です。 –

+0

彼はWindowsからコードを移植しているので、これを考慮に入れて原子変数を導入することができます(long - > std :: atomic ) – Robertas

+1

もちろん、彼は可能ですが、それは彼が求めている質問ではありません。問題は具体的には、 'std :: atomic 'の代わりに 'long *'を渡したいと言っています。 – interjay

1

__atomic_add_fetch GCC拡張GCC 4で

。あなたが書くことができるので、8、C++標準ライブラリは、ビルトイン__atomic_add_fetch GCCとstd::atomic::operator++を実装します。

inline long InterlockedIncrement(long* p) 
{ 
    return __atomic_add_fetch(p, 1, __ATOMIC_SEQ_CST); 
} 

私が打ち鳴らすためにわからないんだけど、__c11_atomic_fetch_addhttp://clang.llvm.org/docs/LanguageExtensions.html

のようないくつかのオプションがあるように思われます他にも触れたように、引数pは標準ライブラリメソッドのみを使用するためにはstd::atomicでなければなりません。アトミックポインタはアトミックポインタが指すものではなく、ポインタに対してのみ作用するため、ポインタをアトミックに変換することは役に立ちません。

+0

また、GCCビルトインはclangで利用できるかもしれません。 – caps

+0

@capsどのような条件で利用できますか? –

+0

私の場合、 'std = C++ 14 'を使ってCentOS 6のClang 3.7.0でgccの標準ライブラリ実装を使用しています。その最後はおそらくキービットです、なぜなら、それは '__atomic_add_fetch'を引っ張っている場所だと思います。私のIDE(OSX上で動作している)はこの機能を認識しません。 – caps

関連する問題