non nullable smart pointers
I've been interested in non nullable smart pointers for a while. I noticed a thread I wanted to check if anyone was still interested in doing it: http://lists.boost.org/Archives/boost/2008/04/135616.php This seems like a worthwhile activity. Null is a legacy element from C that essentially breaks type safety. C++ added references as a way of moving people away from null, but T& obj style references have a number of problems: 1. They have value semantics, which is just plain annoying considering they are *called* references. 2. They use obj.member notation instead of obj->member. 1 is just not usually desireable, and 2 means that there's no way to write a "smart reference" that uses ref.member notation. With that in mind what would a nonnullable pointer be named? I've seen one implemented as a "checked_ptr", but that's a mouthful and doesn't account for the fact that several variations on memory management scheme are needed. I'm thinking: ref<T> myObject; // for a non-nullable pointer with no special memeory management scoped_ref<T> myObject; // for scoped_ptr style memory mangement shared_ref<T> myObject; // you get the idea. I'm also aware of a number of problems with the shared_ptr implementation, specifically that it creates a second allocation for the counter (the counted body problem), and that it always does synchronization, which might have performance overhead for single threaded code (someone else might know more about that than me). It migth be nice to start fresh on these designs now that some perspective has been gained. For the counted body problem I was thinking of creating a make_shared_ref that would create an object and counter adjacent to each other (just put them in the same struct). I put together some proof of concept tempaltes a whie ago and having make_shared_ref<T> behave exactly like new T was somewhat problematic due to overloading issues. Also, you'd need to keep around an extra function pointer in the counter object to delete the struct all together or delete the object seperate object and counter (if they are non-adjacent) and I"m not sure about how that would stack up performance wise. Brendan
On Fri, Nov 14, 2008 at 6:16 PM, Brendan Miller <catphive@catphive.net> wrote:
I'm also aware of a number of problems with the shared_ptr implementation, specifically that it creates a second allocation for the counter (the counted body problem)
Using make_shared avoids the separate allocation for the control block. Shared_ptr frees the user from having to know (or care) about how the object instance was allocated, how many (if any) allocations were made, etc. Optimizing allocations is as easy as supplying a custom allocator to shared_ptr when the object is first created.
and that it always does synchronization, which might have performance overhead for single threaded code
In single-threaded builds, no synchronization is done. In multi-threaded builds, on most platforms shared_ptr uses atomic instructions for mutex-free management of the counters. In theory managing the refcounts is a significant overhead but in practice I'm yet to see this overhead cause me any real issues. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
On Fri, Nov 14, 2008 at 7:23 PM, Emil Dotchevski <emil@revergestudios.com> wrote:
On Fri, Nov 14, 2008 at 6:16 PM, Brendan Miller <catphive@catphive.net> wrote:
I'm also aware of a number of problems with the shared_ptr implementation, specifically that it creates a second allocation for the counter (the counted body problem)
Using make_shared avoids the separate allocation for the control block.
I don't see a make_shared anywhere in the boost shared_ptr documentation... http://www.boost.org/doc/libs/1_36_0/libs/smart_ptr/shared_ptr.htm Am I looking in the wrong place? Yeah, I was wondering why someone hadn't done something like this... but I don't see it documented anywhere. Also, is this in TR1/C++0x's shared_ptr? I've never seen a reference to it anywhere.
On Fri, Nov 14, 2008 at 8:20 PM, Brendan Miller <catphive@catphive.net> wrote:
On Fri, Nov 14, 2008 at 7:23 PM, Emil Dotchevski
On Fri, Nov 14, 2008 at 6:16 PM, Brendan Miller <catphive@catphive.net> wrote:
I'm also aware of a number of problems with the shared_ptr implementation, specifically that it creates a second allocation for the counter (the counted body problem)
Using make_shared avoids the separate allocation for the control block.
I don't see a make_shared anywhere in the boost shared_ptr documentation... http://www.boost.org/doc/libs/1_36_0/libs/smart_ptr/shared_ptr.htm Am I looking in the wrong place?
Yeah, I was wondering why someone hadn't done something like this... but I don't see it documented anywhere. Also, is this in TR1/C++0x's shared_ptr? I've never seen a reference to it anywhere.
I'm not sure about documentation but make_shared is available in Boost: http://svn.boost.org/svn/boost/trunk/boost/make_shared.hpp Also see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm and Peter Dimov's web site http://www.pdimov.com/ for more shared_ptr info. Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
I'm not sure about documentation but make_shared is available in Boost: http://svn.boost.org/svn/boost/trunk/boost/make_shared.hpp
Also see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2351.htm and Peter Dimov's web site http://www.pdimov.com/ for more shared_ptr info.
Excellent! It would be nice if boost documented this though... no one's going to use it if they have to trawl through the header to find out about it.
Brendan Miller skrev:
I've been interested in non nullable smart pointers for a while. I noticed a thread I wanted to check if anyone was still interested in doing it: http://lists.boost.org/Archives/boost/2008/04/135616.php
This seems like a worthwhile activity. Null is a legacy element from C that essentially breaks type safety.
FWIW, Boost.PtrContainer does not allow you to put nulls in containers; if you want nulls you have to ask for it: boost::ptr_vector< boost::nullable<T> > vec; I guess it would be trivial to add something like typedef boost::shared_ptr< boost::non_null<T> > ptr_type; which would not be default constructible, and which would throw if you inserted a null (rather than providing a check in operator->). Peter, is that something that has been considered? -Thorsten
On Sat, Nov 15, 2008 at 2:49 AM, Thorsten Ottosen <thorsten.ottosen@dezide.com> wrote:
Brendan Miller skrev:
I've been interested in non nullable smart pointers for a while. I noticed a thread I wanted to check if anyone was still interested in doing it: http://lists.boost.org/Archives/boost/2008/04/135616.php
This seems like a worthwhile activity. Null is a legacy element from C that essentially breaks type safety.
FWIW, Boost.PtrContainer does not allow you to put nulls in containers; if you want nulls you have to ask for it:
boost::ptr_vector< boost::nullable<T> > vec;
I'm always shocked how many good ideas have already been implemented in boost.
I guess it would be trivial to add something like
typedef boost::shared_ptr< boost::non_null<T> > ptr_type;
which would not be default constructible, and which would throw if you inserted a null (rather than providing a check in operator->).
You're suggesting that there would be a specialization of shared_ptr for shared_ptr<boost::non_null<T>>? That's a good idea, but I have no idea on whether the maintainers of shared_ptr are willing to accept that much more complexity. Also, shared_ptr<non_null<t>> is really a mouthful, but I guess when c++0x comes out you could just do a template using to shared_ref<t> or something for those (such as myself) who want to consistently prohibit null in their code to promote type safety. Really though, if you had a non-nullable reference counted pointer, you'd also want a non-nullable unmanaged pointer, a non-nullable weak pointer, a non-nullable scoped pointer and appropriate conversions, i.e. you can assign a non-null unmanaged pointer to a non-null reference counted pointer and vice versa without a runtime null check being done. That's why I was thinking of just rolling a separate set of pointers, maybe taking shared_ptr and scoped_ptr as starting points. I don't know who the maintainer is, but i wasn't sure whether they would accept a patch with that much added complexity. Brendan
Brendan Miller skrev:
On Sat, Nov 15, 2008 at 2:49 AM, Thorsten Ottosen <thorsten.ottosen@dezide.com> wrote:
Brendan Miller skrev:
I've been interested in non nullable smart pointers for a while. I noticed a thread I wanted to check if anyone was still interested in doing it: http://lists.boost.org/Archives/boost/2008/04/135616.php
This seems like a worthwhile activity. Null is a legacy element from C that essentially breaks type safety. FWIW, Boost.PtrContainer does not allow you to put nulls in containers; if you want nulls you have to ask for it:
boost::ptr_vector< boost::nullable<T> > vec;
I'm always shocked how many good ideas have already been implemented in boost.
I guess it would be trivial to add something like
typedef boost::shared_ptr< boost::non_null<T> > ptr_type;
which would not be default constructible, and which would throw if you inserted a null (rather than providing a check in operator->).
You're suggesting that there would be a specialization of shared_ptr for shared_ptr<boost::non_null<T>>? That's a good idea, but I have no idea on whether the maintainers of shared_ptr are willing to accept that much more complexity.
Well, full specializations is not necessary. Some simple TMP should be enough. -Thorsten
On Mon, Nov 17, 2008 at 1:00 AM, Thorsten Ottosen <thorsten.ottosen@dezide.com> wrote:
Brendan Miller skrev:
On Sat, Nov 15, 2008 at 2:49 AM, Thorsten Ottosen <thorsten.ottosen@dezide.com> wrote:
Brendan Miller skrev:
I've been interested in non nullable smart pointers for a while. I noticed a thread I wanted to check if anyone was still interested in doing it: http://lists.boost.org/Archives/boost/2008/04/135616.php
This seems like a worthwhile activity. Null is a legacy element from C that essentially breaks type safety.
FWIW, Boost.PtrContainer does not allow you to put nulls in containers; if you want nulls you have to ask for it:
boost::ptr_vector< boost::nullable<T> > vec;
I'm always shocked how many good ideas have already been implemented in boost.
I guess it would be trivial to add something like
typedef boost::shared_ptr< boost::non_null<T> > ptr_type;
which would not be default constructible, and which would throw if you inserted a null (rather than providing a check in operator->).
You're suggesting that there would be a specialization of shared_ptr for shared_ptr<boost::non_null<T>>? That's a good idea, but I have no idea on whether the maintainers of shared_ptr are willing to accept that much more complexity.
Well, full specializations is not necessary. Some simple TMP should be enough.
-Thorsten
Well, shared_ptr would need *some* custimization I believe, since it takes a type as a parameter and not a pointer to a type, so the type of the pointer used internally (nullable or non-nullable) can't be specified using the existing interface and implementation. As is, if non_null<T> where a non-null pointer to T, then shared_ptr<non_null<T>> would be a pointer to a pointer (i.e. T**). So for non-nullable smart pointers, you'd either need a policy based implementation, which shared pointer docs seem to indicate is a design choice avoided originally since it opens the door to arbitrary numbers of mutually incompatible shared_ptr's, or something specialization based. Brendan
participants (3)
-
Brendan Miller
-
Emil Dotchevski
-
Thorsten Ottosen