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
.