Entendendo std :: atomic :: compare_exchange_weak () no C ++ 11

bool compare_exchange_weak (T& expected, T val, ..);

compare_exchange_weak() é uma das primitivas de troca de comparação fornecidas em C ++ 11. Estáfraco no sentido de que retorna falso, mesmo que o valor do objeto seja igual aexpected. Isso é devido aofalha espúria em algumas plataformas em que uma sequência de instruções (em vez de uma como no x86) é usada para implementá-la. Nessas plataformas, a troca de contexto, o recarregamento do mesmo endereço (ou linha de cache) por outro encadeamento etc. pode falhar no primitivo. Estáspurious como não é o valor do objeto (não é igual aexpected) que falha na operação. Em vez disso, é um tipo de problema de tempo.

Mas o que me intriga é o que é dito na norma C ++ 11 (ISO / IEC 14882),

29.6.5 .. Uma conseqüência de falhas espúrias é que quase todos os usos de comparação e troca fracas ocorrerão em loop.

Por que tem que estar em um loopquase todos os usos ? Isso significa que devemos fazer um loop quando falha devido a falhas espúrias? Se for esse o caso, por que nos incomodamos em usarcompare_exchange_weak() e escrever o loop nós mesmos? Podemos apenas usarcompare_exchange_strong() que acho que deveria nos livrar de falhas espúrias para nós. Quais são os casos de uso comuns decompare_exchange_weak()?

Outra questão relacionada. Em seu livro "C ++ Concurrency In Action", Anthony diz:

//Because compare_exchange_weak() can fail spuriously, it must typically
//be used in a loop:

bool expected=false;
extern atomic<bool> b; // set somewhere else
while(!b.compare_exchange_weak(expected,true) && !expected);

//In this case, you keep looping as long as expected is still false,
//indicating that the compare_exchange_weak() call failed spuriously.

Porque é!expected existe na condição de loop? Existe para impedir que todos os threads passem fome e não façam progresso por algum tempo?

Edit: (uma última pergunta)

Nas plataformas em que não existe nenhuma instrução CAS de hardware único, as versões fraca e forte são implementadas usando LL / SC (como ARM, PowerPC, etc.). Existe alguma diferença entre os dois loops a seguir? Por que, se houver? (Para mim, eles devem ter desempenho semelhante.)

// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_weak(..))
{ .. }

// use LL/SC (or CAS on x86) and ignore/loop on spurious failures
while (!compare_exchange_strong(..)) 
{ .. }

Eu vim com esta última pergunta que todos vocês mencionam que talvez haja uma diferença de desempenho dentro de um loop. Também é mencionado pelo C ++ 11 Standard (ISO / IEC 14882):

Quando uma comparação e troca está em loop, a versão fraca gera melhor desempenho em algumas plataformas.

Mas, como analisado acima, duas versões em um loop devem fornecer o mesmo desempenho / similar. O que sinto falta?

questionAnswers(4)

yourAnswerToTheQuestion