2

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

Community
  • 1
  • 1
  • 1
    You need to use ordinary synchronization. Even if all operations on a std::shared_ptr were mutually exclusive, nothing prevents threads doing bad things. It's the pointee object you need to prevent unlimited concurrent access to, not the shared_ptr. – Cheers and hth. - Alf Feb 26 '15 at 08:57
  • There is an interesting part about atomic shared pointers somewhere in this video series (note there are 2 videos) by Her Sutter ! https://www.youtube.com/watch?v=c1gO9aB9nbs en https://www.youtube.com/watch?v=CmxkPChOcvw – engf-010 Feb 26 '15 at 10:22
  • That's not part of the C++ standard (yet). Here's [the latest proposal (N4162)](http://www.open-std.org/JTC1/SC22/WG21/docs/papers/2014/n4162.pdf) for `atomic_*_ptr`/`atomic<*_ptr>`. – DanielKO Feb 26 '15 at 10:23

2 Answers2

5

std::atomic<.> can only be used with a 'trivially copyable type'.

std::shared_ptr<std::string> obviously doesn't satisfy those criteria. Somewhere atomic 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:

std::shared_ptr<std::string> s(new std::string("abc"));
std::shared_ptr<std::string> t;
memcpy(&t,&s,sizeof(std::shared_ptr<std::string>));

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 a std::mutex. There is no easy way to provide a lock-free pointer to string. Such an object would usher in a revolution in computing.

Persixty
  • 8,165
  • 2
  • 13
  • 35
  • 1
    LOL this revolution in computing would also destroy the job of a lot of senior engineers, but I don't think we'll see that happen anytime soon. – kuroi neko Feb 26 '15 at 09:44
3

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.

kuroi neko
  • 8,479
  • 1
  • 19
  • 43
  • 1
    By "free atomic functions" I've meant [these](http://en.cppreference.com/w/cpp/memory/shared_ptr/atomic) - I think Herb Sutter referred to them as such in one of his proposals. Thank you for your answer, I'll rethink the design. – user3512240 Feb 26 '15 at 18:44