В Intel MacOSX вы можете использовать встроенную систему атомарных операций. Для 32- или 64-разрядных целых чисел не предусмотрено ни одного атомарного метода get или set, но вы можете создать его из предоставленного CompareAndSwap. Вы можете искать документацию XCode для различных функций OSAtomic. Я написал 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. Некоторые из них работают в Windows 2000 Pro и более поздних версиях, а некоторые (в частности, некоторые из 64-разрядных функций) являются новыми в Vista. На других платформах GCC версии 4.1 и новее имеют различные функции __sync *, такие как __sync_fetch_and_add (). Для других систем вам может потребоваться использовать сборку, и вы можете найти некоторые реализации в браузере SVN для проекта HaikuOS, внутри src / system / libroot / os / arch.