I need to use atomic shared_ptr in my code - I have single-reader-multiple-writers scenario where a small data structure will be copied and overwritten by multiple threads.
After seeing this and this (and my own tests) it seems that free atomic function still aren't working in GCC 4.9.2.
I've tried simply putting shared_ptr in atomic:
#include <atomic>
#include <iostream>
#include <memory>
std::atomic<std::shared_ptr<std::string> > a_var;
void place() {
std::shared_ptr<std::string> ptr1(new std::string("abc"));
a_var.store(ptr1);
}
int main(int argc, const char *argv[]) {
place();
std::shared_ptr<std::string> ptr2 = a_var.load();
std::cout<< *ptr2 << std::endl;
return 0;
}
But after compiling with g++ --std=c++11 -g <filename> -latomic
it throws segfault.
What seems to be happening is that after calling store
a new shared_ptr
is created using a copy constructor, but it's immediately deleted and after exiting place
ptr1 is released, so *ptr2
throws.
Any ideas how can make it work
std::atomic<.>
can only be used with a 'trivially copyable type'.std::shared_ptr<std::string>
obviously doesn't satisfy those criteria. Somewhereatomic
will be copying the object as a block of memory and violating some invariant of one or more of the classes.For example we all know that:
Is both compilable and executable to the end of the copy. It's also a guaranteed recipe for disaster.
In your case
ptr1
doesn't "know" it's been copied so it deletes the string when it (ptr1
) goes out of scope. Then you access the string. Boom. Game Over.The standard way to achieve what you're doing is to protect the
share_ptr
with astd::mutex
. There is no easy way to provide a lock-free pointer to string. Such an object would usher in a revolution in computing.Forget about C++11 shiny toys for a sec and look at what you actually want to achieve.
The thing to protect here is your data structure, not the pointers that refer to it.
I assume by "free atomic function" you mean lock free. There is a very good reason why compilers won't let you throw atomics around too freely. It's because that is less efficient than using plain old blocking synchronization in all but the rarest cases.
C++11 has made playing with atomic variables the latest whim of fashion, but though this stuff is wrapped into a nice coat of syntactic sugar, it's bloody dangerous and leads to unstable and/or inefficient designs when used by anyone but seasoned experts.
In C++14 you'll have
atomic_shared_pointer
, which requires custom code and certainly can't be made to work just by wrapping a shared pointer into an atomic template, but at any rate this would not solve your problem either.