This is a bit of a two part question, all about the atomicity of std::shared_ptr
:
1.
As far as I can tell, std::shared_ptr
Howard's answered the question well already, and Nicol made some good points about the benefits of having a single standard shared pointer type, rather than lots of incompatible ones.
While I completely agree with the committee's decision, I do think there is some benefit to using an unsynchronized shared_ptr
-like type in special cases, so I've investigated the topic a few times.
If I'm not using multiple threads, or if I am using multiple threads but am not sharing pointer ownership across threads, an atomic smart pointer is overkill.
With GCC when your program doesn't use multiple threads shared_ptr doesn't use atomic ops for the refcount. This is done by updating the reference counts via wrapper functions that detect whether the program is multithreaded (on GNU/Linux this is done simply by detecting whether the program links to libpthread.so
) and dispatch to atomic or non-atomic operations accordingly.
I realised many years ago that because GCC's shared_ptr
is implemented in terms of a __shared_ptr__shared_ptr
. Unfortunately because that wasn't an intended use case it didn't quite work optimally before GCC 4.9, and some operations still used the wrapper functions and so dispatched to atomic operations even though you've explicitly requested the _S_single
policy. See point (2) at http://gcc.gnu.org/ml/libstdc++/2007-10/msg00180.html for more details and a patch to GCC to allow the non-atomic implementation to be used even in multithreaded apps. I sat on that patch for years but I finally committed it for GCC 4.9, which allows you to use an alias template like this to define a shared pointer type that is not thread-safe, but is slightly faster:
template
using shared_ptr_unsynchronized = std::__shared_ptr;
This type would not be interoperable with std::shared_ptr
and would only be safe to use when it is guaranteed that the shared_ptr_unsynchronized
objects would never be shared between threads without additional user-provided synchronization.
This is of course completely non-portable, but sometimes that's OK. With the right preprocessor hacks your code would still work fine with other implementations if shared_ptr_unsynchronized
is an alias for shared_ptr
, it would just be a little faster with GCC.
If you're using a GCC before 4.9 you could use that by adding the _Sp_counted_base<_S_single>
explicit specializations to your own code (and ensuring noone ever instantiates __shared_ptr
without including the specializations, to avoid ODR violations.) Adding such specializations of std
types is technically undefined, but would work in practice, because in this case there's no difference between me adding the specializations to GCC or you adding them to your own code.