Quantcast
Channel: Active questions tagged gcc - Stack Overflow
Viewing all articles
Browse latest Browse all 22087

GCC atomic shared_ptr implementation

$
0
0

According to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=57250, GCC 4.9 has support for atomic shared_ptr operations.

Using GCC 4.9.2, I'm able to compile a program that uses atomic shared_ptr. The -mcx16 flag is required, as the GCC implementation on x86_64 apparently requires cmpxchg16b, which makes sense as I would assume that an atomic operation on a shared_ptr would require atomically updating both the pointer itself and the reference count at the same time.

However, when I try to actually use the atomic shared_ptr library, it does not behave as I expect. So, either I am not using this properly, or the GCC implementation is defective. Most of the time I'd be 99% confident that I'm just doing it wrong, but since this is a relatively new feature and since the behavior seems so bizarre, I'm only about 50% confident that it's my fault in this case.

Here is a simple program that creates an atomic shared_ptr, then performs a series of concurrent reads and writes on the 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;
}

When I compile and run, the output is:

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

But this output makes no sense to me. Firstly, after initializing the atomic shared_ptr to a value of 10, when I load it and read the initial value (before any threads are spawned), I get a 0. Secondly, after all the threads join, the value is still 0, even though no thread could have possibly set it to 0. And most bizarrely, after the threads join, the use_count() of the shared_ptr is 0! Yet the atomic shared_ptr object is still in scope, and thus the use count should be 1.

I'm pretty sure the GCC implementation is flawed here, but according to the link I posted above, GCC 4.9 has a completed atomic shared_ptr implementation, and...

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

So... what exactly is going on here? I'd like to get some kind of confirmation that either the GCC 4.9.2 implementation here is flawed or incomplete, or I'm just totally wrong/confused about how to use atomic shared_ptr.


Viewing all articles
Browse latest Browse all 22087

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>