#c #boost #synchronization #atomic #multiplatform
#c #повышение #синхронизация #атомарный #многоплатформенный
Вопрос:
До std::atomic
тех пор, пока он не будет доступен, каков мультиплатформенный (Windows и Linux) способ атомарного увеличения переменной?
В настоящее время я использую boost::detail::atomic_count
, но он находится в boost::detail
пространстве имен, и я не знаю, безопасно ли его использовать.
Комментарии:
1. Вы смотрели на рассматриваемый в настоящее время Boost. Атомарная библиотека?
2.
std::atomic
уже доступен. Нет?3. MSVC и GCC теперь имеют поддержку std::atomic . Также есть stdthread.co.uk
Ответ №1:
Многоплатформенный, но специфичный для компилятора способ заключается в использовании GCC __sync_fetch_and_add
.
Или определите такую функцию самостоятельно с помощью небольшой условной компиляции:
#ifdef __GNUC__
#define atomic_inc(ptr) __sync_fetch_and_add ((ptr), 1)
#elif defined (_WIN32)
#define atomic_inc(ptr) InterlockedIncrement ((ptr))
#else
#error "Need some more porting work here"
#endif
Комментарии:
1. __sync_fetch_and_add и MSVC InterlockedIncrement не эквивалентны по их возвращаемым типам. __sync_fetch_and_add возвращает предыдущее значение ptr, а InterlockedIncrement возвращает результирующее значение увеличенного ptr. Что вам нужно использовать, так это «__sync_add_и_fetch», чтобы быть эквивалентными / взаимозаменяемыми.
2. Кроме того,
InterlockedIncrement
только для 32-разрядных значений.
Ответ №2:
Используйте InterlockedExchangeAdd вместо InterlockedIncrement — это полный аналог, с __sync_fetch_и_add;
#ifdef __GNUC__
#define atomic_inc(ptr) __sync_fetch_and_add ((ptr), 1)
#elif defined (_WIN32)
#define atomic_inc(ptr) InterlockedExchangeAdd ((ptr), 1)
#else
#error "Need some more porting work here"
#endif
Вы можете найти проверенные аналоги вызовов msvc / gcc здесь (x86)