Intel MacOSXでは、組み込みのシステムアトミック操作を使用できます。32ビットまたは64ビット整数のアトミックgetまたはsetは提供されていませんが、提供されているCompareAndSwapから構築できます。さまざまなOSAtomic関数については、XCodeのドキュメントを検索することをお勧めします。以下に64ビットバージョンを作成しました。32ビットバージョンは、同様の名前の関数を使用して実行できます。
#include <libkern/OSAtomic.h>
// bool OSAtomicCompareAndSwap64Barrier(int64_t oldValue, int64_t newValue, int64_t *theValue);
void AtomicSet(uint64_t *target, uint64_t new_value)
{
while (true)
{
uint64_t old_value = *target;
if (OSAtomicCompareAndSwap64Barrier(old_value, new_value, target)) return;
}
}
uint64_t AtomicGet(uint64_t *target)
{
while (true)
{
int64 value = *target;
if (OSAtomicCompareAndSwap64Barrier(value, value, target)) return value;
}
}
AppleのOSAtomicCompareAndSwap関数は、次の操作をアトミックに実行することに注意してください。
if (*theValue != oldValue) return false;
*theValue = newValue;
return true;
上記の例では、これを使用して、最初に古い値を取得し、次にターゲットメモリの値を交換しようとすることでSetメソッドを作成します。スワップが成功した場合、それはメモリの値がスワップ時の古い値のままであり、スワップ中に新しい値が与えられることを示します(それ自体はアトミックです)。これで完了です。成功しない場合は、他のスレッドが、値を取得してからリセットしようとしたときに、その間の値を変更することによって干渉しています。その場合は、最小限のペナルティでループして再試行できます。
Getメソッドの背後にある考え方は、最初に値を取得できることです(別のスレッドが干渉している場合、実際の値である場合とそうでない場合があります)。次に、値をそれ自体と交換して、最初のグラブがアトミック値と等しいことを確認するだけです。
私はこれを私のコンパイラに対してチェックしていませんので、タイプミスを許してください。
OSXについて具体的に言及しましたが、他のプラットフォームで作業する必要がある場合に備えて、Windowsには多数のInterlocked *関数があり、MSDNドキュメントでそれらを検索できます。それらのいくつかはWindows2000Pro以降で動作し、いくつか(特に64ビット関数のいくつか)はVistaで新しく追加されました。他のプラットフォームでは、GCCバージョン4.1以降には、__ sync_fetch_and_add()などのさまざまな__sync*関数があります。他のシステムでは、アセンブリを使用する必要がある場合があります。いくつかの実装は、HaikuOSプロジェクトのSVNブラウザーのsrc / system / libroot / os/arch内にあります。