Nell'implementazione di boost di shared_ptr
, utilizza relaxed memory ordering to increment its reference count. Ciò sembra sicuro poiché i decrementi usano acquisire/rilasciare per assicurarsi che eventuali decrementi precedenti siano visibili al thread prima di rilasciare la memoria. Questo metodo sembra corretto e appare in Herb Sutters talk on atomicsPerché l'implementazione di shared_ptr da parte di libC++ utilizza barriere di memoria complete anziché rilassate?
In attuazione ++ libc 's utilizza full memory barriers
template <class T>
inline T
increment(T& t) _NOEXCEPT
{
return __sync_add_and_fetch(&t, 1);
}
template <class T>
inline T
decrement(T& t) _NOEXCEPT
{
return __sync_add_and_fetch(&t, -1);
}
} // name
C'è una ragione per questa decisione? Ci sono differenze di prestazioni o di sicurezza tra di loro?
In base a [dettagli dell'implementazione qui] (http://en.cppreference.com/w/cpp/memory/shared_ptr), si dice "Per soddisfare i requisiti di sicurezza dei thread, i contatori di riferimento sono in genere incrementati e decrementati usando un equivalente di std :: atomic :: fetch_add con std :: memory_order_relaxed. " Speravo di trovare la fonte per confermare la dichiarazione, ma ho difficoltà a trovare la documentazione online del codice sorgente di libC++ per gcc (anche se sono solo ricerche ingenue di Google, forse qualcuno può fornire un link). Tuttavia, noto che il tuo collegamento è per LLVM. – Suedocode
Chi ha scritto quel codice, quando, perché e cos'altro hanno scritto ... se solo ci fosse un modo per scoprirlo. ;) –
@Aggieboy Penso che il mirror che ho linkato sia la fonte di libC++ su GCC, basta compilarlo con '-gcc-toolchain'. libstd ++ (libreria standard predefinita su GCC) usa '__gnu_cxx :: __ exchange_and_add', che credo sia anche una barriera completa, ma non ne sono sicuro. Sembra che sia comune conoscenza che dovrebbe essere implementato con barriere rilassate ma non riesco a trovare alcuna libreria oltre a boost che lo fa –