Итак, я начинаю знакомиться с типами C++ 11 <atomic>
. Раньше, когда у меня был атомный флаг, я обычно просто блокировал мьютекс, прежде чем обращаться к нему. Общей потребностью было бы проверить, равен ли флаг false
, и если да, то атомически установите его на true
, а затем сделайте что-нибудь. Таким образом, в основном это будет достигнуто, как это, где flag
простой bool
:Основное использование условных выражений с std :: atomic <T>
{
std::lock_guard<std::mutex> lock(my_mutex);
if (!flag)
{
flag = true;
// do something;
}
}
Итак, теперь я пытаюсь выяснить, как то же самое может быть достигнуто с <atomic>
. docs говорят, что оператор присваивания и operator T
атомного типа являются атомарными операциями. Однако, если я изменю flag
к std::atomic<bool>
, я думаю, я не могу просто сказать:
if (!flag)
{
flag = true;
// do something
}
... потому что даже если выражение (!flag)
атомная, и назначение flag = true
атомарный, нет ничего, чтобы предотвратить еще один поток от изменения флага между этими двумя утверждениями.
Итак, если я правильно понимаю, здесь, единственное правильное использование - на всех - из условных с атомарными типами, где результат условными может изменить атомные переменный, чтобы использовать Compare и операцию свопа ? Я прав?
Таким образом, я должен был бы сказать:
bool expected = false;
if (flag.compare_exchange_weak(expected, true))
{
// do something
}
Я правильно в моем понимании здесь?
['std :: atomic_flag'] (http://en.cppreference.com/w/cpp/atomic/atomic_flag) существует для конкретного варианта использования, который вы описываете, и тем более гарантируется, бесплатно на всех платформах. Вы бы использовали метод 'test_and_set', который является атомарным.Вы также можете использовать 'std :: atomic' и выполнить на нем 'fetch_add', который является атомарным и даст вам предыдущее значение во время выполнения приращения (это часто бывает быстрее, чем CAS на большинстве архитектур, хотя я предполагаю, что не быстрее, чем 'std :: atomic_flag', что было бы предпочтительным в этом случае). –
Cameron
Правильно - но кажется, что нет возможности просто атомизировать «проверку» значения атомного флага (без его настройки) - или есть? Документы не определяют 'operator bool' или что бы то ни было, что бы включить выражение' if (flag) '. Я понимаю, что не задал этого требования в своем вопросе - мне просто интересно. Говоря о том, почему ... почему * нет * есть способ просто проверить атомный флаг, не устанавливая его? – Siler
Правильно, вы должны установить его, чтобы протестировать его (что эквивалентно вашему образцу кода, как он написан в данный момент, за исключением того, что он является атомарным). Если вам нужно протестировать его по отдельности, я предлагаю использовать метод 'fetch_add' или' compare_exchange_strong' (который намного понятнее и [так же быстро, как 'fetch_add' (' lock xadd') на x86] (http: // www.agner.org/optimize/instruction_tables.pdf)). – Cameron