12

一部の Windows C++ コードを iOS に移植する際に、Win32 のlong InterlockedIncrement(long *p)呼び出しの実装を提供する必要があります。で定義されている関数を使用すると、これは簡単<libkern/OSAtomic.h>です。

ただし、主にC++ 11の機能だけを使用して、OSに依存しない方法で記述できるかどうか疑問に思ってい<atomic>ます。私はこれを思いつきましたが、私が望むものを達成できるかどうかはわかりません:

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

これは機能しますか?それで十分ですか?2 つの行はアトミックではありませんが、インクリメントはアトミックにする必要があります。これがここで重要です。

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

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

正しい方法は何ですか?

もう一度編集: ポインターの実装がコンパイルされます...

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

しかし、アトミック型をインクリメントしないため、これは機能しないのではないかと思いますが、ポインターが指す値はアトミックではありません。

4

3 に答える 3

12

あなたの実装例は、毎回ポインターから新しいアトミックを構築しています。これは std::atomic の意図した使用法ではなく、あなたが望むように機能するとは思いません。

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

既存の(十分にテストされた)コードをそのまま残したいと思っていることは理解していますが、あなたの場合はできないと思います。

于 2012-11-15T17:11:49.140 に答える
3

__atomic_add_fetchGCC 拡張機能

GCC 4.8 では、C++ 標準ライブラリstd::atomic::operator++が GCC 組み込みの を実装している__atomic_add_fetchため、次のように記述できます。

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

clangについてはわかりませんが、__c11_atomic_fetch_add http://clang.llvm.org/docs/LanguageExtensions.htmlのようないくつかのオプションがあるようです

他の人が述べたように、引数p自体はstd::atomic、標準ライブラリ メソッドのみを使用するためのものでなければなりません。アトミック ポインターはポインターが指すものではなく、ポインターに対してのみ作用するため、ポインターをアトミックに変換しても役に立ちません。

于 2015-06-17T07:06:32.290 に答える
2

操作を使用できると思いますatomic_fetch_addこちらの例をご覧ください。

于 2012-11-15T14:44:49.090 に答える