2013-04-16 20 views
11

Molti dei C++ 11 operazioni CAS (ad esempio, atomic_compare_exchange_weak, atomic_compare_exchange_strong) prendere due puntatori e un valore, vale a dire, in questo modo:Perché le operazioni CAS C++ 11 richiedono due parametri puntatore?

bool atomic_compare_exchange(T* pointer, T* expected,  // pseudodeclaration! 
          T desired); 

Al contrario, le operazioni di CAS da Microsoft, gcc, e Intel tutti prendono un puntatore e due valori:

long InterlockedCompareExchange(long* pointer, long desired,  // Microsoft 
           long expected); 

int __sync_bool_compare_and_swap (T* pointer, T expected,   // gcc and 
            T desired);      // Intel 

Perché i C++ 11 funzioni CAS prendere due puntatori e un valore al posto di quello che sembra essere un puntatore più convenzionale e due valori?

+0

'__sync_bool _...' restituisce un bool * *. –

+1

@KerrekSB: la firma che ho mostrato è stata copiata dal manuale Intel. Supponevo che gcc usasse la stessa firma. Ora vedo che non è così. – KnowItAllWannabe

risposta

18

Il modo C++ 11 è più utile: se lo scambio non riesce, quindi *expected è aggiornato al nuovo valore corrente. Che lo rende facile da usare la funzione in un ciclo:

T value = x.load(); 
T newvalue = frob(value); 

while (!atomic_compare_exchange(&x, &value, newvalue)) 
{ 
    newvalue = frob(value); 
} 

Con la firma di Microsoft, verificando se l'operazione è riuscita è più ingombrante, e idem per la versione di GCC __sync_type. Con GCC __sync_bool, è addirittura necessario eseguire un altro carico ogni volta che lo scambio fallisce.

2

Non vedo perché non avresti entrambi. Nel mio caso d'uso la versione C++ è meno utile. Voglio aspettare fino a quando una variabile ha qualche valore, quindi voglio impostarlo su un nuovo valore.

Con instrinsics GCC:

while (!__sync_bool_compare_and_swap(&value, expected, desired)) { } 

Con C++ 11:

auto tmp = expected; 
while (!value.compare_exchange_weak(tmp,desired)) 
{ 
    tmp = expected; 
} 
Problemi correlati