Implementação atomic shared_ptr do GCC

De acordo comhttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250, O GCC 4.9 tem suporte para atômicashared_ptr operações.

Usando o GCC 4.9.2, sou capaz de compilar um programa que usa atômicashared_ptr. o-mcx16 é necessário, pois a implementação do GCC em x86_64 aparentemente requercmpxchg16b, o que faz sentido, como eu assumiria que uma operação atômica em umshared_ptr exigiria atualizar atomicamente o ponteiro em si e a contagem de referência ao mesmo tempo.

No entanto, quando eu tento realmenteusar o atômicoshared_ptr biblioteca, ele não se comporta como eu esperava. Portanto, não estou usando isso corretamente ou a implementação do GCC está com defeito. Na maioria das vezes, eu estaria 99% confiante de que estou fazendo errado, mas como esse é um recurso relativamente novo e como o comportamento parece tão bizarro, estou apenas 50% confiante de que é minha culpa nisso. caso.

Aqui está um programa simples que cria um atômicoshared_ptr, em seguida, executa uma série de leituras e gravações simultâneas no 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;
}

Quando eu compilar e executar, a saída é:

~$ 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

Mas essa saída não faz sentido para mim. Em primeiro lugar, depois de inicializar o atômicoshared_ptr para um valor de10, quando carrego e leio o valor inicial (antes que qualquer thread seja gerado), recebo uma0. Em segundo lugar, após a junção de todos os threads, o valor ainda é0, mesmo que nenhum encadeamento possa defini-lo como0. E o mais estranho é que, após a junção dos tópicos, ouse_count() do shared_ptr é0! No entanto, o atômicoshared_ptr objeto ainda está no escopo e, portanto, a contagem de uso deve ser1.

Tenho certeza de que a implementação do GCC é falha aqui, mas de acordo com o link que eu postei acima, o GCC 4.9 possui um atômico completoshared_ptr implementação e ...

~$ gcc --version
~$ gcc (Debian 4.9.2-10) 4.9.2

Então ... o que exatamente está acontecendo aqui? Gostaria de obter algum tipo de confirmação de que a implementação do GCC 4.9.2 aqui é falha ou incompleta, ou estou totalmente errado / confuso sobre como usar o atômicoshared_ptr.

questionAnswers(1)

yourAnswerToTheQuestion