2014-11-25 4 views
1

Если у меня есть атомный переменный следующий образ:неразрушающий атомный add?

#include <atomic> 

std::atomic<int> a = 5; 

Я хотел бы атомарно проверить (a + 4) меньше, чем другие переменный, без перезаписывания исходного значения a:

if(a.something(4) < another_variable){ 
    //Do not want a to be incremented by 4 at this point 
} 

Я быстро проверил атомные fetch_and_add() и ++, и все они, похоже, впоследствии увеличивают значение переменной a. Есть ли способ, которым я могу атомизировать приращение к тесту, без постоянного результата?

+3

'another_variable - = 4'? –

+6

Что должно быть атомарным, если нет видимого побочного эффекта вне этой темы? Атомный по отношению к чему? – Useless

+2

Что не так с помощью 'a + 4

ответ

3
if(a + 4 < another_variable) // ... 

Это лучшее, что вы можете получить с помощью одного атома. Вы свободны от данных, так как чтение атома является безопасным для одновременной записи, и все последующие операции происходят с копией исходного значения атома. Более многословным, но функционально эквивалентный вариант будет:

int const copy_of_a = a.load(); 
if(copy_of_a + 4 < another_variable) // ... 

Это также лучшее, что вы можете получить с точки зрения синхронизации. Вы можете быть обеспокоены тем фактом, что a может быть изменен в другом потоке на значение, которое изменит результат if.

Предположим, существует функция, которая сделала всю операцию атомарной:

if(a.plus4IsLessThan(another_variable) // ... 

Затем приходит ли одновременное изменение a во времени, чтобы изменить результат теста еще не известно. Вы не получили никаких дополнительных гарантий с точки зрения синхронизации.

Если это проблема для вашей программы, это означает, что вам нужен более мощный механизм синхронизации. Вероятно, std::mutex будет хорошим началом.

+2

std :: atomic :: operator T() эквивалентен std :: atomic :: load(), поэтому 'if (a + 4

+0

@JayMiller Хорошая точка. У меня лично есть привычка писать 'load()' s, чтобы я мог быстрее идентифицировать атомы в своем собственном коде, но, конечно, ваша версия может быть предпочтительной для лучшей читаемости. – ComicSansMS

+2

Это зависит от того, оптимизируете ли вы для «Achtung! Atomics!» или «эй, это всего лишь номер, не волнуйся о своей довольно маленькой голове об атоматике прямо сейчас», и это может варьироваться от использования до использования. –

1

Вы можете просто сделать:

if (a + 4 < another_variable) { ... 

Какой должна быть идентична:

if (a.load() + 4 < another_variable) { ... 

По определению (§29.6.5/16-17, здесь A «относится к одному из атомное типы»и„C относится к соответствующему неатомическому типу“):

A::operator C() const volatile noexcept; 
A::operator C() const noexcept; 

эффекты: load()

Возвращает: Результат load()

Ни один из которых изменяют a.

Смежные вопросы