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.

Respuestas a la pregunta(1)

Su respuesta a la pregunta