В Mac OS X и Windows есть встроенные функции CompareAndSwap, которые вы должны использовать в любом случае (InterlockedCompareExchange () и OSAtomicCompareAndSwapPtrBarrier () соответственно). Таким образом, будет работать независимо от компиляторов на этих платформах.
В других Unix-системах это немного сложнее, если вы используете GCC 4.1 или новее, вы можете просто использовать его встроенную функцию __sync_val_compare_and_swap (), и многие, хотя и не все компиляторы Unix, поддерживают разумные расширения gcc, так как большая часть кода, созданного в Linux, предполагает они присутствуют.
Так что, если вы хотите обернуть их так, чтобы они работали практически со всеми компиляторами для всех процессоров в OS X и Windows, а также с GCC и некоторыми другими компиляторами на других платформах, вы должны сделать что-то вроде:
boolean CompareAndSwapPointer(volatile * void * ptr,
void * new_value,
void * old_value) {
#if __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ >= 1050
return OSAtomicCompareAndSwapPtr (old_value, new_value, ptr);
#elif defined(_MSC_VER)
return InterlockedCompareExchange(ptr, new_value, old_value);
#elif (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) > 40100
return __sync_val_compare_and_swap(ptr, old_value, new_value);
#else
# error No implementation
#endif
}
Это не проверено, но я думаю, что это должно быть правильно. Обратите внимание, как все библиотеки ОС принимают аргументы в разных порядках; -)
Очевидно, что вы можете сделать несколько версий для сравнения разного размера, а также поменять их и обернуть в шаблоны, если хотите. API в основном основаны на C и кодируют информацию о типах в функции таким образом, что это немного неприятно для людей, привыкших параметризировать типы с помощью шаблонов.