Me pregunto cómo se std::atomic_refpuede implementar de manera eficiente (uno std::mutexpor objeto) para objetos no atómicos, ya que la siguiente propiedad parece bastante difícil de aplicar:
Las operaciones atómicas aplicadas a un objeto a través de atomic_ref son atómicas con respecto a las operaciones atómicas aplicadas a través de cualquier otra atomic_ref que haga referencia al mismo objeto.
En particular, el siguiente código:
void set(std::vector<Big> &objs, size_t i, const Big &val) {
std::atomic_ref RefI{objs[i]};
RefI.store(val);
}
Parece bastante difícil de implementar, ya std::atomic_refque de alguna manera necesitaría elegir cada vez lo mismo std::mutex(a menos que sea un gran bloqueo maestro compartido por todos los objetos del mismo tipo).
¿Me estoy perdiendo de algo? ¿O cada objeto es responsable de implementar std::atomic_refy, por lo tanto, ser atómico o llevar un std::mutex?

Respuestas:
La implementación es casi exactamente la misma que
std::atomic<T>ella misma. Este no es un problema nuevo.Vea ¿Dónde está el bloqueo para un std :: atomic? Una aplicación típica de
std::atomic/std::atomic_refuna tabla hash estático de cerraduras, indexada por dirección, para objetos no-libre de bloqueo. Las colisiones de hash solo conducen a una contención adicional, no a un problema de corrección. (Los bloqueos siguen siendo imposibles; los bloqueos solo son utilizados por funciones atómicas que nunca intentan tomar 2 a la vez).En GCC, por ejemplo,
std::atomic_refes solo otra forma de invocar__atomic_storeun objeto. (Consulte el manual de GCC: incorporaciones atómicas )El compilador sabe si
Tes lo suficientemente pequeño como para ser libre de bloqueo o no. Si no, llama a la función de biblioteca libatomic que usará el bloqueo.(Dato curioso: eso significa que solo funciona si el objeto tiene suficiente alineación
atomic<T>. Pero en muchas plataformas de 32 bits, incluida x86,uint64_tpuede que solo tenga una alineación de 4 bytes.atomic_refEn dicho objeto se compilará y ejecutará, pero en realidad no será atómico si el compilador utiliza una carga / almacenamiento SSE de 8 bytes en modo de 32 bits para implementarlo. Afortunadamente no hay peligro para los objetos que tienenalignof(T) == sizeof(T), como la mayoría de los tipos primitivos en arquitecturas de 64 bits).fuente
atomic<T>estaba permitido en tipos no atómicos (aunque técnicamente podría asignarse unomutex, ya que posee el objeto). Gracias por la explicación, tiene sentido.Una implementación puede usar un hash basado en la dirección del objeto para determinar cuál de un conjunto de bloqueos adquirir mientras se realiza la operación.
fuente
shared_ptrobjetos. github.com/gcc-mirror/gcc/blob/master/libstdc%2B%2B-v3/src/…