Quindi sto iniziando a familiarizzare con i tipi di C++ 11 <atomic>
. In passato, quando avevo una bandiera atomica, di solito chiudevo semplicemente un mutex prima di accedervi. Un'esigenza comune sarebbe quella di verificare se il flag è false
e, in caso affermativo, impostarlo atomicamente su true
e quindi fare qualcosa. Quindi, in pratica questo sarebbe compiuto come questo, dove flag
è un semplice bool
:Uso di base di condizionali con std :: atomico <T>
{
std::lock_guard<std::mutex> lock(my_mutex);
if (!flag)
{
flag = true;
// do something;
}
}
Così, ora sto cercando di capire come la stessa cosa può essere realizzato con <atomic>
. Il docs dice che l'operatore di assegnazione e operator T
di un tipo atomico sono operazioni atomiche. Tuttavia, se cambio flag
a std::atomic<bool>
, immagino non posso semplice esempio:
if (!flag)
{
flag = true;
// do something
}
... perché, anche se l'espressione (!flag)
è atomico, e l'assegnazione flag = true
è atomico, non c'è nulla per impedire un altro thread dalla modifica del flag tra queste due istruzioni.
Quindi, se ho capito bene qui, l'unico corretto utilizzo - affatto - dei condizionali con i tipi atomici, in cui il risultato del condizionale potrebbe modificare la variabile atomica, è quello di utilizzare l'e il funzionamento Confronta Swap ? Ho ragione?
Così, ho dovuto dire:
bool expected = false;
if (flag.compare_exchange_weak(expected, true))
{
// do something
}
Ho ragione nella mia comprensione qui?
['std :: atomic_flag'] (http://en.cppreference.com/w/cpp/atomic/atomic_flag) esiste esattamente per il caso d'uso che stai descrivendo, e per di più è garantito che sia lock- gratuito su tutte le piattaforme Dovresti usare il metodo 'test_and_set', che è atomico.Puoi anche usare un 'std :: atomic' ed eseguire un 'fetch_add' su di esso, che è atomico e ti darà il valore precedente nel momento in cui viene eseguito l'incremento (questo è spesso più veloce di un CAS sulla maggior parte delle architetture, anche se immagino non più veloce di 'std :: atomic_flag', che sarebbe la mia preferenza in questo caso). –
Cameron
Giusto - ma sembra che non sia possibile semplicemente "controllare" atomicamente il valore di una bandiera atomica (senza impostarla) - oppure è presente? I documenti non definiscono un 'operatore bool' o qualsiasi cosa che abilita l'espressione 'if (flag)'. Mi rendo conto di non aver specificato questo requisito nella mia domanda - Mi sto solo chiedendo. A proposito di ... perché * non * c'è un modo per controllare semplicemente la bandiera atomica senza impostarla? – Siler
Esatto, devi impostarlo per testarlo (che è equivalente al tuo codice di esempio come è attualmente scritto, tranne che è atomico). Se è necessario testarlo in modo indipendente, suggerisco di usare l'approccio 'fetch_add', o' compare_exchange_strong' (che è molto più chiaro, ed è [altrettanto veloce di 'fetch_add' (' lock xadd') su x86] (http: // www.agner.org/optimize/instruction_tables.pdf)). – Cameron