12

By reading the c++11 draft n3242, section 20.7.2.5, looks like we have atomic operations on shared_ptr, which enables us do lock-free on complicated structure without worrying about GC/memory leak.

However, I couldn't use it successfully in GCC-4.7.0. I simply tested the following program

#include <atomic>
#include <memory>
#include <string>

struct X {
    int x;
    double y;
    std::string s;
};

int main() {
    std::shared_ptr<X> x(new X);
    auto p = std::atomic_load(&x);
}

and it has compiler error:

c.cpp:13:33: error: no matching function for call to ‘atomic_load(std::shared_ptr<X>*)’

Does anyone know what I missed here? Or is it simply gcc hasn't implemented that yet?

Kan Li
  • 8,557
  • 8
  • 53
  • 93
  • `shared_ptr<>`'s internal reference count will be atomically incremented and decremented without writing any special. What are you trying to do with `atomic_load` exactly..? – ildjarn Jun 09 '12 at 01:00
  • @ildjarn, read this http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2674.htm – Kan Li Jun 09 '12 at 01:02
  • @ildjarn If threads are changing what a shared_ptr variable points to you need to avoid data races when accessing the shared_ptr itself. – bames53 Jun 09 '12 at 01:04
  • @icando: This wasn't necessarily accepted to the standard, it's just a proposal. I would check for it in the new standard. – Collin Dauphinee Jun 09 '12 at 01:05
  • @dauphic : The C++11 standard does indeed have a `template shared_ptr atomic_load(const shared_ptr* p)` function template (§20.7.2.5/6-8). – ildjarn Jun 09 '12 at 01:06
  • The referenced article suggests that the functionality is available in `boost::shared_ptr` (for versions of boost >= 1.36). Maybe you could use that if your compiler doesn't support it directly. (Though this is likely to be a spinlock based implementation too) – Michael Anderson Jun 09 '12 at 03:12
  • 1
    @icando - We *can* have lock free operations, but you have to check `atomic_is_lock_free()` for the type you are going to use. It is all "if available". – Bo Persson Jun 09 '12 at 09:47
  • To fill out to what @Bo said: the only atomic type that is required to be lock free is `atomic_flag`. For the `atomic_integral` types, there are macros that you can query at compile time, as well as member functions and free functions that you can call at runtime. – Pete Becker Aug 13 '12 at 21:52
  • Did you figure this out eventually? GCC 4.9 still doesn't seem to support it... – stav Aug 02 '15 at 07:44

3 Answers3

3

There is a proposal to deprecate these atomic_store/atomic_load methods for shared_ptr in favor of the new atomic_shared_ptr class: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4162.pdf

So by the time you get a libstc++ version with atomic_load it may very well contain the new atomic pointers already, which are better in several aspects.

MSVC STL has implemented these methods a while ago, and libc++ also claims full C++11/14 compliance, so they must be available in its latest versions.

Massimiliano
  • 16,770
  • 10
  • 69
  • 112
2

Looks like it's just not in libstdc++ yet.

It's also not in libc++

VS11 beta has it. I think this is the first thing I've found in VS11's library that wasn't in libc++.

bames53
  • 86,085
  • 15
  • 179
  • 244
  • do you have any idea when this could be implemented by GCC? – Kan Li Jun 09 '12 at 01:28
  • I don't have VS11 by my hand so I am curious how VS11 implements atomic_load/atomic_store/atomic_compare_and_exchange. Is it implemented via spin lock? – Kan Li Jun 09 '12 at 02:43
  • 1
    Yes, it appears to use a spin lock `_Shared_ptr_spin_lock` (I only checked atomic_load, but I assume the others are the same). – bames53 Jun 09 '12 at 02:46
  • so this is not a lock free implementation. Not sure if a lock free implementation even exists. – Kan Li Jun 09 '12 at 02:51
  • @icando : What do you perceive to be the difference between a spin wait and a spin lock? – ildjarn Jun 09 '12 at 02:55
  • 1
    @ildjarn, I don't see them much different. My point is, the major usage for atomic shared_ptr is to implement lock-free atomic read-compute-update to complicated structure. Refer to http://open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2674.htm, if the atomic_load and atomic_compare_exchange themselves are implemented using some spin lock, the whole do{compute();}while(atomic_compare_exchange()); loop is then super costly and I don't see it useful anymore. In this case, I would rather using a read/write lock instead. – Kan Li Jun 09 '12 at 03:02
  • @icando : The whole `do{compute();}while(atomic_compare_exchange());` loop is purely in user-mode, and thus super-_cheap_ compared to a proper lock (assuming the wait duration is very short, as it would be during a simple increment/decrement). Ring3->Ring1 transitions cost tens-of-thousands cycles more, even if there's no real wait needed. – ildjarn Jun 09 '12 at 03:05
  • 1
    @ildjarn, it really depends. On very low concurrency, spin lock may be good enough, but on high concurrency, where lots of threads competing the same spin lock, lots of CPU are just wasted on the spin. It would be better to release the CPU to other threads. – Kan Li Jun 09 '12 at 03:09
-6

Use clang++ with -std=c++11 for compiling the code that should get it working.

alokasok
  • 1
  • 1