0

私たちが持っている場合:

__int32 some_var = 0;

を呼び出すための最良の(もしあれば)方法InterlockedExchangeInterlockedIncrementおよびを必要とする他のインターロックされた関数LONG*some_var何ですか?

LONGどのWindowsでも32ビットであることが保証されているので、渡すだけでおそらく安全(long*) some_varです。しかし、私にはかなり醜いようで、安全であるという確認を見つけることができません。

longポータブルではないため、タイプをに変更することはできません。正確に32ビットタイプが必要です。

更新:移植可能な不可分操作を提供するライブラリのいくつかの研究は、誰もキャストについて気にしないことを示しました。いくつかの例:

Apache Portable Runtime(APR)

typedef WINBASEAPI apr_uint32_t (WINAPI * apr_atomic_win32_ptr_val_fn)
    (apr_uint32_t volatile *, 
     apr_uint32_t);

APR_DECLARE(apr_uint32_t) apr_atomic_add32(volatile apr_uint32_t *mem, apr_uint32_t val)
{
#if (defined(_M_IA64) || defined(_M_AMD64))
    return InterlockedExchangeAdd(mem, val);
#elif defined(__MINGW32__)
    return InterlockedExchangeAdd((long *)mem, val);
#else
    return ((apr_atomic_win32_ptr_val_fn)InterlockedExchangeAdd)(mem, val);
#endif
}

atom_ops

AO_INLINE AO_t
AO_fetch_and_sub1_full (volatile AO_t *p)
{
  return _InterlockedDecrement64((LONGLONG volatile *)p) + 1;
}
4

6 に答える 6

2

まあ、それは岩と難しい場所です。アトミックインクリメントは、強力なプラットフォーム実装の詳細です。そもそもLONGtypedefが存在するのはそのためです。20年後または50年後の将来のオペレーティングシステムでは、そのタイプが再定義される可能性があります。たとえば、256ビットのコアが一般的であり、アトミックインクリメントの動作が異なる場合。知るか。

真にポータブルなコードを書きたい場合は、真にポータブルなタイプを使用する必要があります。LONGのように。そして、それを機能させるのはあなたの代わりにマイクロソフトの責任になるでしょう。

しばらくの間、32ビット整数になる予定です。心配しないでください。

于 2010-09-03T16:20:56.753 に答える
1

「インターロックされた」アトミック操作のファミリー全体も移植性がないため、タイプをlongに変更して、移植性を残したほうがよいでしょう。

ちなみに、補足として、interlockedは整数のオーバーロードをサポートしていると思いました。おそらくそれは.netだけです。

于 2010-09-03T15:14:54.333 に答える
1

さて、__int32ポータブルタイプでもありませ。したがって、問題を解決するための私の提案は、typedefを使用することです。Windowsでは、次のことができます。

typedef LONG my_int32;

...そしてそのような型へのポインタを安全にに渡しますInterlockedExchange()。他のシステムでは、32ビットタイプのものを使用します。たとえば、ある場合は、次のようstdint.hに実行できます。

typedef int32_t my_int32;
于 2010-09-04T03:52:56.910 に答える
0

アサーションが失敗した場合にのみ問題を実行assert(sizeof(LONG) == sizeof(some_var))して心配してください。YAGNI。アサーションが保持されている限り、を使用できますreinterpret_cast<LONG*>(&some_var)

于 2010-09-03T16:44:09.487 に答える
0

面白いことに、InterlockedExchangeがあります。これはLONG​​を使用するWindowsAPIであり、 _InterlockedExchangeは長い*を必要とするmsvcコンパイラ組み込み関数です。

移植性が呼び出されたため、 GCCアトミック組み込み関数のページもリンクします。

ただし、要点はよく理解されています。MSVCは、32ビットビルドにはILP32LLP64データモデルを使用し、64ビットビルドにはLLP64を使用します。GCCベースのツールチェーン(MinGWなど)はWindows用に存在し、LP64モデルを非常にうまく実装する可能性があります-面白いことにつながります!'long'は64ビットですが、LONGは32ビットです。

Microsoftコンパイラに固執している場合は、心配する必要はありません。

したがって、結論として、次のようになります。1.渡される値は「volatile」で修飾する必要があります。2.(a)32ビットの量を使用しているため(そしてそれがあなたの要件です)、(b)明示的に32ビット形式のInterlockedXXX APIを使用しているため-血まみれのキャストを実行してそれで実行するのは100%安全です:InterlockedIncrementはすべてのビットサイズで32ビット値で動作し、変数はすべてのビットサイズで明示的に32ビットになります-使用中のデータモデルが異なっていても。

キャストは安全です。理由もなく物事を複雑にしすぎないでください。

于 2010-09-04T20:29:32.430 に答える
0

ハンス・パッサントはそれを非常にうまく表現しています:

「アトミックインクリメントは、強力なプラットフォーム実装の詳細です。」

これが、実装がタイプ固有のオーバーロードを提供する理由です。

atomic_opsそのようなプロジェクトの1つです。

理論的には、すべてのインターロックされた関数は、本格的なロックを使用して実装できます。これは、プラットフォームの詳細に依存します:-)-しかし、これは、ターゲットハードウェアプラットフォームでサポートされているタイプと関数の実際のパフォーマンスの過剰です。

この点に関しては、いくつかの標準化が行われています。たとえば、ここここでも同様の質問に回答してください。

于 2010-09-05T01:00:40.707 に答える