Implementación de GCC atomic shared_ptr
De acuerdo ahttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250, GCC 4.9 tiene soporte para atómicashared_ptr
operaciones
Usando GCC 4.9.2, puedo compilar un programa que usa atomicshared_ptr
. los-mcx16
Se requiere un indicador, ya que la implementación de GCC en x86_64 aparentemente requierecmpxchg16b
, lo cual tiene sentido ya que supondría que una operación atómica en unshared_ptr
requeriría actualizar atómicamente tanto el puntero como el recuento de referencias al mismo tiempo.
Sin embargo, cuando intento realmenteutilizar el atómicoshared_ptr
biblioteca, no se comporta como esperaba. Entonces, o no estoy usando esto correctamente, o la implementación de GCC es defectuosa. La mayoría de las veces estaría 99% seguro de que lo estoy haciendo mal, pero dado que esta es una característica relativamente nueva y dado que el comportamiento parece tan extraño, solo estoy un 50% seguro de que es mi culpa en esto caso.
Aquí hay un programa simple que crea un atómicoshared_ptr
, luego realiza una serie de lecturas y escrituras concurrentes en shared_ptr:
void test()
{
std::atomic<std::shared_ptr<int>> p(std::shared_ptr<int>(new int(10)));
std::cout << "Use count : " << p.load().use_count() << std::endl;
std::cout << "Initial value of p : " << *(p.load()) << std::endl;
std::vector<std::thread> threads;
const std::size_t num_threads = 8;
for (std::size_t i = 0; i != num_threads; ++i)
{
threads.emplace_back([&p, i](){
std::shared_ptr<int> x = p.load();
while (!p.compare_exchange_weak(
x,
std::shared_ptr<int>(new int(i + 5))
)) ;
});
}
for (auto& t : threads) t.join();
std::cout << "Use count : " << p.load().use_count() << std::endl;
std::cout << "Final value of p : " << *(p.load()) << std::endl;
}
Cuando compilo y ejecuto, el resultado es:
~$ g++ test2.cpp -o test2 -std=c++11 -lpthread -mcx16
~$ ./test2
Use count : 1
Initial value of p : 0
Use count : 0
Final value of p : 0
Pero esta salida no tiene sentido para mí. Primero, después de inicializar el atómicoshared_ptr
a un valor de10
, cuando lo cargo y leo el valor inicial (antes de que se generen subprocesos), obtengo un0
. En segundo lugar, después de unir todos los hilos, el valor sigue siendo0
, a pesar de que ningún hilo podría haberlo configurado0
. Y lo más extraño, después de que se unen los hilos, eluse_count()
del shared_ptr es0
! Sin embargo, lo atómicoshared_ptr
El objeto todavía está dentro del alcance y, por lo tanto, el recuento de uso debe ser1
.
Estoy bastante seguro de que la implementación de GCC es defectuosa aquí, pero de acuerdo con el enlace que publiqué anteriormente, GCC 4.9 tiene un atómico completoshared_ptr
implementación y...
~$ gcc --version
~$ gcc (Debian 4.9.2-10) 4.9.2
Entonces ... ¿qué está pasando exactamente aquí? Me gustaría obtener algún tipo de confirmación de que la implementación de GCC 4.9.2 aquí es defectuosa o incompleta, o estoy totalmente equivocado / confundido sobre cómo usar atomicshared_ptr
.