Smart pointers question

Started by
35 comments, last by Hodgman 12 years, 1 month ago

Also, what about people writing single-threaded code (or properly scheduled multi-threaded code) -- why should their usage of shared_ptr be 100x slower, just in case you need their useless "thread safety" guarantee? Well written multi-threaded code doesn't need shared variables, so enforcing atomic counters is forcing a bad design choice onto your users...

Fortunately, boost has options for removing thread safety overhead if you're writing single threaded code. Defining BOOST_DISABLE_THREADS will disable thread support for all of boost (commonly done through boost/config/user.hpp) and BOOST_SP_DISABLE_THREADS will disable it for shared_ptr.
Advertisement

Apparently in C++11, shared_ptr is more "thread safe", allowing you to concurrently read/write without experiencing the above crash... however, that's even worse, because to overcome the above issue, you've got to add a lot of extra complexity to the memory manager that allocates/deletes your ref-counters.... which is unnecessary in a properly designed multi-threaded system... sad.png


Isn't it far better to have the language provide safe and easy to use tools out of the box and let the programmer develop their own faster, unsafe versions if needed than to do things the other way around though ?
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
Isn't it far better to have the language provide safe and easy to use tools out of the box and let the programmer develop their own faster, unsafe versions if needed than to do things the other way around though ?[/quote]

Use C# then. That is the "safe and easy" language.

It has better memory model which solves such problems systematically without overhead.

Shared_ptrs invalidate the use of C++. All you end up is overly verbose, slow-to-compile, vastly inefficient language that is worse than managed platforms in all things that matter.

Use C++ if you want or need to manage memory and other hardware resources yourself. Otherwise, managed languages win just about every time.


None of this means that shared_ptrs and similar have no place in C++. But they do expose the commonly missing separation between resource management and resource usage. Ideally, being C++, code would look like this:void mutator(Foo * fooRef);
void mutator(Foo & fooRef);

mutator(my_sp->get());
mutator(*my_sp);
Or something similar. Reason being shared pointers don't cover all important cases, they merely help sharing ownership. Shared pointers should only be used for sharing, which is surprisingly rare.

They will completely fail if used like Java/C#, which share references like they are going out of fashion. Shared_ and other pointers don't make ownership problems go away but merely make associated problems simpler.


Not separating resource management from use however will result in all of the above problems, including potentially exponential time complexity of individual operations.

Isn't it far better to have the language provide safe and easy to use tools out of the box and let the programmer develop their own faster, unsafe versions if needed than to do things the other way around though ?


Use C# then. That is the "safe and easy" language.
[/quote]

So you are saying that because C# is safe and easy C++ shouldn't have a threadsafe shared pointers ? (What about a string class and dynamic containers are those bad things to have in a C++ standard library aswell ?), The fact that another language is safe and easy is not a valid argument for why C++ shouldn't provide a safe and easy to use standard library, The low level stuff is still there to be used WHEN they are needed (Which almost never is 100% of your codebase)

Yes, shared pointers shouldn't be used as you use C# or Java references, they should only be used to share ownership of data(Which is why they exist) and having a thread safe reference count when multiple threads can own the same data is a good thing. If you want shared pointers without thread safe reference counts you can just do:

template<typename T> using st_shared_ptr = __shared_ptr<T, __gnu_cxx::_S_single>;

with gcc so its not like it is a big issue, You only pay for what you use, when you use it.
[size="1"]I don't suffer from insanity, I'm enjoying every minute of it.
The voices in my head may not be real, but they have some good ideas!
Yeah I mean if two threads are reading/writing the shared_ptr object itself (i.e. changing the ref-counter that it points to). If there's only one reference, and then two threads try to simultaneously


So the problem wouldn't be two threads modifying the ref-counter, but two threads doing so through the same shared_ptr? In that case everything would still be the way I remember it. The reference counter is "thread safe", but not the actual shared_ptr or data behind it.

One consequence of the issue you describe is that new shared_ptr should always be created and passed on by an existing owner and that any one ownership should be limited to a single thread. Quite a few implicit rules for something that's supposed to make things easier.
f@dzhttp://festini.device-zero.de
boost::shared_ptr has the same thread-safety as a normal pointer.
You're not allowed to do

Thread 1:[font=courier new,courier,monospace] a = null;[/font]
Thread 2:[font=courier new,courier,monospace] shared_ptr<T> b = a;[/font]
[/quote]
with normal pointers either.
boost::shared_ptr has the same thread-safety as a normal pointer.
You're not allowed to do
Thread 1:[font=courier new,courier,monospace] a = null;[/font]
Thread 2:[font=courier new,courier,monospace] shared_ptr<T> b = a;[/font]
with normal pointers either.[/quote]Yeah, my point was that boost's [font=courier new,courier,monospace]shared_ptr[/font]s do have the same lack of "thread-safety" guarantees as raw pointers, but boost's [font=courier new,courier,monospace]shared_ptr[/font] also does make use of slow atomic operations (cache-line mutexes) in order to make them "thread safe"... while still being as "thread unsafe" as raw pointers?

Also, [font=courier new,courier,monospace]shared_ptr[/font] is worse than regular pointers in the above case. With a regular pointer (on most CPUs), [font=courier new,courier,monospace]b[/font] will either be equal to the original value of [font=courier new,courier,monospace]a[/font], or it will be equal to [font=courier new,courier,monospace]null[/font]. With [font=courier new,courier,monospace]shared_ptr[/font]s, the above code will also perform either of those two possibilities, but there's also a 3rd possibility which is an access-violation/segfault crash when incrementing the reference counter.
Isn't it far better to have the language provide safe and easy to use tools out of the box and let the programmer develop their own faster, unsafe versions if needed than to do things the other way around though ?
I'd say the standard library should provide generic tools out of the box that can be used in as many different ways as possible, as this is what the STL/SC++L has always tried to do.
A switch to choose the level of "thread safety" provided would be nice, such as:
If you want shared pointers without thread safe reference counts you can just do: ... with gcc so its not like it is a big issue, You only pay for what you use, when you use it
That's neat - do you know if the official C++11 spec has a similar feature, or is this going to be a compiler-specific thing?
Defining ... BOOST_SP_DISABLE_THREADS will disable it for shared_ptr.
That's handy, but kind of useless if other parts of your code base do want the default shared_ptr behaviour. The above template argument implementation is much more usable.

This topic is closed to new replies.

Advertisement