intrusive_ptr design question

View: New views
20 Messages — Rating Filter:   Alert me  
< Prev | 1 - 2 | Next >

intrusive_ptr design question

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

I was wondering from a design perspective, why was it decided that
intrusive_ptr should rely on user-defined free functions
intrusive_ptr_add_ref and intrusive_ptr_release to handle the
reference counting?  This makes it somewhat inconvenient, for some
constant type T, to support having two different instances of
intrusive_ptr<T>, each of which use a different reference counting
strategy.

If there's a clever way to allow this that I'm missing please advise.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Scott McMurray-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

2009/7/5 Zachary Turner <divisortheory@...>:
> I was wondering from a design perspective, why was it decided that
> intrusive_ptr should rely on user-defined free functions
> intrusive_ptr_add_ref and intrusive_ptr_release to handle the
> reference counting?  This makes it somewhat inconvenient, for some
> constant type T, to support having two different instances of
> intrusive_ptr<T>, each of which use a different reference counting
> strategy.
>

I'm rather confused why you'd want to keep 2 different reference
counts in an object.  As a workaround though, why not just use struct
T1 : T {}; and struct T2 : T {}; if you need 2 distinct kinds?
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Daniel Hulme-4 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Sun, Jul 05, 2009 at 07:58:49PM -0500, Zachary Turner wrote:
> I was wondering from a design perspective, why was it decided that
> intrusive_ptr should rely on user-defined free functions
> intrusive_ptr_add_ref and intrusive_ptr_release to handle the
> reference counting?

One of the main reasons for intrusive_ptr is to have smart pointers to
third-party classes that already have their own refcount. Since you
can't add a member to a class you don't control, using member functions
to manipulate the refcount would rule out that use. The expectation in
this case would be that the user would write these two free functions to
just call the appropriate member functions on the third-party class.

> This makes it somewhat inconvenient, for some
> constant type T, to support having two different instances of
> intrusive_ptr<T>, each of which use a different reference counting
> strategy.
>
> If there's a clever way to allow this that I'm missing please advise.

I must admit, I'm not really sure what you are trying to achieve. It
sounds like you have some instances of T, and you want some of them to
store their reference count in some way, and the rest to have a
completely unrelated way of storing their reference count. But if this
is the case, it sounds like you actually have two different types, and
Scott's solution sounds right; and even so, I don't know what you hope
to achieve by that.

--
"It must be accepted as a principle that the rifle,  effective as it is,
cannot  replace  the effect  produced  by the  speed of  the horse,  the
magnetism of the charge, and the terror of cold steel."
  -- British Cavalry training manual, 1907 ::: http://surreal.istic.org/


_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

signature.asc (204 bytes) Download Attachment

Re: intrusive_ptr design question

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 2:04 AM, Daniel Hulme<st@...> wrote:

> On Sun, Jul 05, 2009 at 07:58:49PM -0500, Zachary Turner wrote:
>> I was wondering from a design perspective, why was it decided that
>> intrusive_ptr should rely on user-defined free functions
>> intrusive_ptr_add_ref and intrusive_ptr_release to handle the
>> reference counting?
>
> One of the main reasons for intrusive_ptr is to have smart pointers to
> third-party classes that already have their own refcount. Since you
> can't add a member to a class you don't control, using member functions
> to manipulate the refcount would rule out that use. The expectation in
> this case would be that the user would write these two free functions to
> just call the appropriate member functions on the third-party class.
But why not just allow the intrusive_ptr to accept those free
functions as constructor arguments, allowing me to pass different free
functions for different instances?


>
>> This makes it somewhat inconvenient, for some
>> constant type T, to support having two different instances of
>> intrusive_ptr<T>, each of which use a different reference counting
>> strategy.
>>
>> If there's a clever way to allow this that I'm missing please advise.
>
> I must admit, I'm not really sure what you are trying to achieve. It
> sounds like you have some instances of T, and you want some of them to
> store their reference count in some way, and the rest to have a
> completely unrelated way of storing their reference count. But if this
> is the case, it sounds like you actually have two different types, and
> Scott's solution sounds right; and even so, I don't know what you hope
> to achieve by that.
>

That is, in fact, the main problem I see.  I don't think reference
counting *should* be tied to a particular type.  I guess the original
set of use cases for intrusive_ptr consisted of exactly 1 use case.
Namely, "allow smart pointer wrapping of objects which provide their
own reference count".  But I guess I'd like to use it for a slightly
different purpose: allowing smart pointer wrapping of objects with a
customizable reference counting scheme.  I guess the name
"intrusive_ptr" really makes it sound like it's more the original use
case, but there's nothing else that really comes close ot fitting the
bill, and intrusive_ptr would serve very nicely if it allowed one to
specify the reference counting functions on a per-instance level.

Imagine, for example, you wanted single-threaded and multi-threaded
versions of a reference counting function.  Obviously you'd want to
use the single threaded version whenever possible since it avoids the
overhead of acquiring / releasing a mutex to udpate the reference
count.  But occasionally you might really need a multi-threaded
ref-counted pointer.  In this case you could simply construct it with
different ref-counting functions.  For that particular example, it
even fits into the original intrusive_ptr use case where you're just
changing *how* you modify the original object's reference count,
instead of changing what you modify.

Scott's workaround is ok, but it's definitely not going to scale as it
will result in combinatorial growth.

Maybe what I'm really after is an implementation of shared_ptr that
allows one to provide the shared_count implementation?
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Frank Mori Hess :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Monday 06 July 2009, Zachary Turner wrote:

> >
> > One of the main reasons for intrusive_ptr is to have smart pointers to
> > third-party classes that already have their own refcount. Since you
> > can't add a member to a class you don't control, using member functions
> > to manipulate the refcount would rule out that use. The expectation in
> > this case would be that the user would write these two free functions to
> > just call the appropriate member functions on the third-party class.
>
> But why not just allow the intrusive_ptr to accept those free
> functions as constructor arguments, allowing me to pass different free
> functions for different instances?

Because you'd have to store 2 function pointers in every intrusive_ptr object?  
Why don't you just store the function pointers in your class?  Then for
example intrusive_ptr_add_ref can call some member function of your class,
which in turn calls its object's internal function pointer.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkpSCNoACgkQ5vihyNWuA4UQ8QCeIx4/EO6K8wWBFhe6ZRKzNAMC
Zf8AoNRlsNgAqoJvpHiHtGB0XKQEjqqr
=wGgt
-----END PGP SIGNATURE-----
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 9:23 AM, Frank Mori Hess<frank.hess@...> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Monday 06 July 2009, Zachary Turner wrote:
>> >
>> > One of the main reasons for intrusive_ptr is to have smart pointers to
>> > third-party classes that already have their own refcount. Since you
>> > can't add a member to a class you don't control, using member functions
>> > to manipulate the refcount would rule out that use. The expectation in
>> > this case would be that the user would write these two free functions to
>> > just call the appropriate member functions on the third-party class.
>>
>> But why not just allow the intrusive_ptr to accept those free
>> functions as constructor arguments, allowing me to pass different free
>> functions for different instances?
>
> Because you'd have to store 2 function pointers in every intrusive_ptr object?
> Why don't you just store the function pointers in your class?  Then for
> example intrusive_ptr_add_ref can call some member function of your class,
> which in turn calls its object's internal function pointer.
>

You shouldn't have to store 2 function pointers for every
intrusive_ptr object.  You should only have to store 2 function
pointers per instance pointed to, and then 1 reference to some shared
structure in each intrusive_ptr object.  Much like shared_ptr
currently does.

Also, maybe the object is part of some library that I didn't write,
but I still want to provide reference counting for it through some
mechanism other than that which is provided by shared_ptr.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Frank Mori Hess :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Monday 06 July 2009, Zachary Turner wrote:
> You shouldn't have to store 2 function pointers for every
> intrusive_ptr object.  You should only have to store 2 function
> pointers per instance pointed to, and then 1 reference to some shared
> structure in each intrusive_ptr object.  Much like shared_ptr
> currently does.

You'd still need a pointer in every intrusive_ptr object to point at the
shared_structure, plus you'd have to do dynamic allocation of the shared
object.  That is never going to fly.

- From the "main reasons to use intrusive_ptr" section of its documentation:

"The memory footprint of intrusive_ptr is the same as the corresponding raw
pointer;"

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkpSExoACgkQ5vihyNWuA4UXtwCeOYuF/Jdap1ajhsd7rI0e9bYa
wY8AoMxu8bHr8+brBAMq+cGF+Ndkt2Nb
=WNH1
-----END PGP SIGNATURE-----
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 10:07 AM, Frank Mori Hess<frank.hess@...> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Monday 06 July 2009, Zachary Turner wrote:
>> You shouldn't have to store 2 function pointers for every
>> intrusive_ptr object.  You should only have to store 2 function
>> pointers per instance pointed to, and then 1 reference to some shared
>> structure in each intrusive_ptr object.  Much like shared_ptr
>> currently does.
>
> You'd still need a pointer in every intrusive_ptr object to point at the
> shared_structure, plus you'd have to do dynamic allocation of the shared
> object.  That is never going to fly.
>
> - From the "main reasons to use intrusive_ptr" section of its documentation:
>
> "The memory footprint of intrusive_ptr is the same as the corresponding raw
> pointer;"
>

Ok, so let me rephrase then: Is there a case to be made for a more
flexible shared_ptr (either through modification or through a new
class addition) that allows one to provide custom reference counting
semantics much the same way that shared_ptr allows one to provide
custom deletion semantics?
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Stewart, Robert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Zachary Turner wrote:
>
> Ok, so let me rephrase then: Is there a case to be made for a more
> flexible shared_ptr (either through modification or through a new
> class addition) that allows one to provide custom reference counting
> semantics much the same way that shared_ptr allows one to provide
> custom deletion semantics?

I haven't followed your discussion closely, so I may have the wrong idea, but don't you run the risk of mixing the different ref counting techniques on objects of the same type?  If the ref counting scheme isn't part of the smart pointer type, then all instances must do ref counting the same way.

IOW, if all instances are my_ref_counter<T>, then having some manipulate the ref count of T's one way and others doing it another means that you can reference the same T instance from different my_ref_counter<T>'s which can manipulate the ref count differently.  Put that in context of thread safety and you can see how a non-thread safe my_ref_counter<T> can wreak havoc on thread code that expects a T's ref count to be manipulated by thread safe my_ref_counter<T>s.

_____
Rob Stewart                           robert.stewart@...
Software Engineer, Core Software      using std::disclaimer;
Susquehanna International Group, LLP  http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 10:32 AM, Stewart, Robert<Robert.Stewart@...> wrote:
> Zachary Turner wrote:
>>
>> Ok, so let me rephrase then: Is there a case to be made for a more
>> flexible shared_ptr (either through modification or through a new
>> class addition) that allows one to provide custom reference counting
>> semantics much the same way that shared_ptr allows one to provide
>> custom deletion semantics?
>
> I haven't followed your discussion closely, so I may have the wrong idea, but don't you run the risk of mixing the different ref counting techniques on objects of the same type?  If the ref counting scheme isn't part of the smart pointer type, then all instances must do ref counting the same way.

That's correct.  The way I have envisioned is analagous to the way
shared_ptr allows you to specify a custom deleter.  Whenever a copy is
made, the new copy gets the same deleter.  That way all copies agree
on the deletion semantics.  As long as all copies of the shared
pointer that refer to the same underlying instance of pointed-to
object agree on reference counting semantics, everything should be ok
right?
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Stewart, Robert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Zachary Turner wrote:

> On Mon, Jul 6, 2009 at 10:32 AM, Stewart,
> Robert<Robert.Stewart@...> wrote:
> > Zachary Turner wrote:
> >>
> >> Ok, so let me rephrase then: Is there a case to be made for
> >> a more flexible shared_ptr (either through modification or
> >> through a new class addition) that allows one to provide
> >> custom reference counting semantics much the same way that
> >> shared_ptr allows one to provide custom deletion semantics?
> >
> > I haven't followed your discussion closely, so I may have the
> > wrong idea, but don't you run the risk of mixing the
> > different ref counting techniques on objects of the same
> > type?  If the ref counting scheme isn't part of the smart
> > pointer type, then all instances must do ref counting the
> > same way.
>
> That's correct.  The way I have envisioned is analagous to the
> way shared_ptr allows you to specify a custom deleter.
> Whenever a copy is made, the new copy gets the same deleter.
> That way all copies agree on the deletion semantics.  As long
> as all copies of the shared pointer that refer to the same
> underlying instance of pointed-to object agree on reference
> counting semantics, everything should be ok right?

Deleting with the wrong deleter is an obvious failure which is likely to crash an application, but only happens once per object.  Manipulating a reference count, tens, hundreds, or more times, exposes a much greater danger.  Yes, copies will agree on how to manipulate the reference count, but the same memory can be referenced by separately constructed, non-copied smart pointer instances.

_____
Rob Stewart                           robert.stewart@...
Software Engineer, Core Software      using std::disclaimer;
Susquehanna International Group, LLP  http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 10:50 AM, Stewart, Robert<Robert.Stewart@...> wrote:

> Zachary Turner wrote:
>> That's correct.  The way I have envisioned is analagous to the
>> way shared_ptr allows you to specify a custom deleter.
>> Whenever a copy is made, the new copy gets the same deleter.
>> That way all copies agree on the deletion semantics.  As long
>> as all copies of the shared pointer that refer to the same
>> underlying instance of pointed-to object agree on reference
>> counting semantics, everything should be ok right?
>
> Deleting with the wrong deleter is an obvious failure which is likely to crash an application, but only happens once per object.  Manipulating a reference count, tens, hundreds, or more times, exposes a much greater danger.  Yes, copies will agree on how to manipulate the reference count, but the same memory can be referenced by separately constructed, non-copied smart pointer instances.
>

Could you elaborate a bit more?  I'm not sure I understand.  Of course
it's up to the programmer to specify correct reference counting
functions and construct shared_ptr instances correctly or else the
behavior will be undefined.  Are you saying that the problem would be
with something like this?

T* t = new T();

shared_ptr<T> ptr_t(t, multi_threaded_ref_counter());
shared_ptr<T> ptr_t2(t);

Causing the instance to be deleted twice eventually?  If so, how is
that different from:

T* t = new T();

shared_ptr<T> ptr_t(t);
shared_ptr<T> ptr_t2(t);

Or for that matter, from:

T* t = new T();

shared_ptr<T> ptr_t(t);
delete t;


Currently all copies of a shared_ptr agree on reference conting
strategy because they are all hardcoded to use
boost::detail::shared_count.  If they all use
foo::bar::mt_shared_count, or better yet if shared_count could be
parameterized with a template such as:

namespace boost { namespace detail {

template<class ref_counter>
class shared_count
{
};


where ref_counter is a class that provides a static interface guarantee such as:

struct ref_counter
{
   long add_ref();
   long release();
};


then there wouldn't even be any extra space overhead, since these
functions could be specified inline by the user.  With correct use of
default template arguments, shared_ptr could be modified to support
this while still allowing current syntax to select the existing shared
pointer ref counting scheme, making it backwards compatible.


If I misunderstood your statement though, please let me know.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Peter Dimov-5 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Zachary Turner wrote:
> Ok, so let me rephrase then: Is there a case to be made for a more
> flexible shared_ptr (either through modification or through a new
> class addition) that allows one to provide custom reference counting
> semantics much the same way that shared_ptr allows one to provide
> custom deletion semantics?

This is not unreasonable. It can't be done currently because the
sp_counted_base members that implement the reference counting are
non-virtual and inline.

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Gottlob Frege :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 11:07 AM, Frank Mori Hess<frank.hess@...> wrote:

> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
>
> On Monday 06 July 2009, Zachary Turner wrote:
>> You shouldn't have to store 2 function pointers for every
>> intrusive_ptr object.  You should only have to store 2 function
>> pointers per instance pointed to, and then 1 reference to some shared
>> structure in each intrusive_ptr object.  Much like shared_ptr
>> currently does.
>
> You'd still need a pointer in every intrusive_ptr object to point at the
> shared_structure, plus you'd have to do dynamic allocation of the shared
> object.  That is never going to fly.
>
> - From the "main reasons to use intrusive_ptr" section of its documentation:
>
> "The memory footprint of intrusive_ptr is the same as the corresponding raw
> pointer;"
>

I'm not sure if this does what the OP wants, but the ref counting
could be a policy:

template <typename T> default_intrusive_ptr_refcount_policy
{
   static void add_ref(T * t)
   {
      // by default call the global function
      intrusive_ptr_add_ref(t);
   }
   static void remove_ref(T * t)
   {
      // by default call the global function
      intrusive_ptr_remove_ref(t);
   }
};

template intrusive_ptr<typename T, typename RefCountPolicy =
default_intrusive_ptr_refcount_policy<T> >
{
   // intrusive_ptr details...
   // on add ref, we call RefCountPolicy::add_ref(t)
   // on remove ref, we call RefCountPolicy::remove_ref(t)
};

// examples:
struct Foo { ... };
struct Bar { ... };

intrusive_ptr<Foo> pFoo; // usual intrusive_ptr, same as always

struct BarRefCountPolicy1
{
   static add_ref(Bar * bar)
   {
       // add ref to bar some way
   };
   static remove_ref(Bar * bar)
   {
       // remove ref some way
   }
};

struct BarRefCountPolicy2
{
   static add_ref(Bar * bar)
   {
       // add ref to bar some *pther* way
   };
   static remove_ref(Bar * bar)
   {
       // remove ref some *other* way
   }
};

intrusive_ptr<Bar, BarRefCountPolicy1> pBar1;
intrusive_ptr<Bar, BarRefCountPolicy2> pBar2;

For better or worse...

?

Tony
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Stewart, Robert :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Zachary Turner wrote:

> On Mon, Jul 6, 2009 at 10:50 AM, Stewart,
> Robert<Robert.Stewart@...> wrote:
> > Zachary Turner wrote:
> >> That's correct.  The way I have envisioned is analagous to the
> >> way shared_ptr allows you to specify a custom deleter.
> >> Whenever a copy is made, the new copy gets the same deleter.
> >> That way all copies agree on the deletion semantics.  As long
> >> as all copies of the shared pointer that refer to the same
> >> underlying instance of pointed-to object agree on reference
> >> counting semantics, everything should be ok right?
> >
> > object.  Manipulating a reference count, tens, hundreds, or
> > more times, exposes a much greater danger.  Yes, copies will
> > agree on how to manipulate the reference count, but the same
> > memory can be referenced by separately constructed,
> > non-copied smart pointer instances.
>
> Could you elaborate a bit more?  I'm not sure I understand.  Of
> course it's up to the programmer to specify correct reference
> counting functions and construct shared_ptr instances correctly
> or else the behavior will be undefined.  Are you saying that

An interface that permits ready misuse is questionable.

> the problem would be with something like this?
>
> T* t = new T();
>
> shared_ptr<T> ptr_t(t, multi_threaded_ref_counter());
> shared_ptr<T> ptr_t2(t);
>
> Causing the instance to be deleted twice eventually?  If so, how

No.  More below.

> is that different from:
>
> T* t = new T();
>
> shared_ptr<T> ptr_t(t);
> shared_ptr<T> ptr_t2(t);

That can be found using memory analysis tools which reveal the double delete.

> Or for that matter, from:
>
> T* t = new T();
>
> shared_ptr<T> ptr_t(t);
> delete t;

Likewise.

My concern is the following, assuming "counter" is a class that supports your notion of construction time specification of referencing counting:

   int * x(new int);
   counter<int> a(x, unsafe_ref_count); // not thread safe
   ...
   counter<int> b(x, safe_ref_count); // thread safe

In these cases, assume that (un)safe_ref_count package the reference counting logic in some handy way not specified ATM.

Note that threaded code assumes it can access x's memory safely, using b, because of using safe_ref_count.  Also note that other code can use a to manipulate x's reference count and access x's memory at the same time.  That means that b's memory and reference count are not thread safe after all.  This same effect can come about in a number of ways.  If you copy a or b, the copy will use the same reference counting scheme, of course.  However, a and b are the same type, so they can interoperate in ways that are either unexpected or cannot be discovered until runtime.

You said (or implied, I don't recall offhand) that you'd supply the increment/decrement ref count functions to the constructor.  That means that (un)safe_ref_count actually represent a pair of function pointers.  Obviously, that interface precludes optimization opportunities -- at least in many cases -- and permits pairing the wrong functions.

You could supply an object with such a pair of functions on it that counter can call.  By grouping the functions in a UDT, you eliminate the chance of incorrect pairing and increase the chance of optimization.

OTOH, if you embed the reference counting behavior into the type of the smart pointer -- counter<int, safe_ref_counter>, for example -- you reduce the opportunities of different parts of the code using different reference counting behavior for the same memory.  The compiler can catch cases of misuse.  Furthermore, the policy class groups the function pair in one type, thus eliminating the chance to combine them incorrectly.

Boost.SmartPtr currently traffics in counter<int> types (shared_ptr<T>, intrusive_ptr<T>, etc.) and not in counter<int,policy> types, thus safe usage of your idea cannot be added to those types and must be done with a policy class in a new smart pointer type.

HTH,

_____
Rob Stewart                           robert.stewart@...
Software Engineer, Core Software      using std::disclaimer;
Susquehanna International Group, LLP  http://www.sig.com

IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Zachary Turner-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Mon, Jul 6, 2009 at 2:31 PM, Stewart, Robert <Robert.Stewart@...>wrote:

> You could supply an object with such a pair of functions on it that counter
> can call.  By grouping the functions in a UDT, you eliminate the chance of
> incorrect pairing and increase the chance of optimization.
>
> OTOH, if you embed the reference counting behavior into the type of the
> smart pointer -- counter<int, safe_ref_counter>, for example -- you reduce
> the opportunities of different parts of the code using different reference
> counting behavior for the same memory.  The compiler can catch cases of
> misuse.  Furthermore, the policy class groups the function pair in one type,
> thus eliminating the chance to combine them incorrectly.
>
> Boost.SmartPtr currently traffics in counter<int> types (shared_ptr<T>,
> intrusive_ptr<T>, etc.) and not in counter<int,policy> types, thus safe
> usage of your idea cannot be added to those types and must be done with a
> policy class in a new smart pointer type.
>

Thanks for the clarification.  I think we basically agree in that case.  My
original proposal didn't mention anything about a ref counting policy, but I
kind of arrived at the conclusion that that was the best way to do it anyway
(see towards the end of my previous post).


Making major interface changes to existing libraries is always inherently
risky but is there any reason that adding a policy to shared_ptr, with a
default policy template argument that uses the existing ref counting
strategy, would be bad?  I can't think of any scenarios that this would
break existing code, except maybe if someone was using a shared_ptr to
parameterize a class that was expecting a template template parameter, and
this seems pretty unlikely.

It seems that it would be easier to do this than to design yet another smart
pointer class, which would then have to work correctly in the presence of
all the other multitude of smart pointer classes.

In theory, intrusive_ptr and weak_ptr could then even become special cases
of shared_ptr by having boost supply policies implementing weak_ptr /
intrusive_ptr reference semantics.  Note that I haven't actually thought
about that aspect in tremendous detail, but it seems like it could be made
to work.  Even the requirement of intrusive_ptr to have the same memory
footprint of a raw pointer should be do-able if it doesn't instantiate the
policy class as a member of the smart pointer.
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Frank Mori Hess :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

On Monday 06 July 2009, Zachary Turner wrote:
> Making major interface changes to existing libraries is always inherently
> risky but is there any reason that adding a policy to shared_ptr, with a
> default policy template argument that uses the existing ref counting
> strategy, would be bad?

The FAQ of the shared_ptr documentation addresses this question.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (GNU/Linux)

iEYEARECAAYFAkpSaH0ACgkQ5vihyNWuA4VAjQCgkhd0/dlTLHukJxGADLC4DUfG
fmcAn27Ggst7A8rQcy/5mgfhnYYVczZT
=dcNY
-----END PGP SIGNATURE-----
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Ulrich Eckhardt-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Monday 06 July 2009 17:23:41 Zachary Turner wrote:
> Is there a case to be made for a more flexible shared_ptr (either
> through modification or through a new class addition) that allows
> one to provide custom reference counting semantics much the same way
> that shared_ptr allows one to provide custom deletion semantics?


Maybe it's already there: shared_ptr doesn't care if the passed deleter
actually deletes anything. If you now take an object with an existing
reference count, you just increment that count and pass the function that
decrements it as deleter function to a shared_ptr constructor. This creates a
parallel reference count, but it should be safe. Nothing can pull the object
from under the shared_ptr's feet because it holds a reference. The shared_ptr
doesn't destroy the object either, at most it decrements the reference count.

Uli

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Neil Groves-3 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wed, Jul 8, 2009 at 8:21 PM, Ulrich Eckhardt <doomster@...> wrote:

> On Monday 06 July 2009 17:23:41 Zachary Turner wrote:
> > Is there a case to be made for a more flexible shared_ptr (either
> > through modification or through a new class addition) that allows
> > one to provide custom reference counting semantics much the same way
> > that shared_ptr allows one to provide custom deletion semantics?
>
>
> Maybe it's already there: shared_ptr doesn't care if the passed deleter
> actually deletes anything. If you now take an object with an existing
> reference count, you just increment that count and pass the function that
> decrements it as deleter function to a shared_ptr constructor. This creates
> a
> parallel reference count, but it should be safe. Nothing can pull the
> object
> from under the shared_ptr's feet because it holds a reference. The
> shared_ptr
> doesn't destroy the object either, at most it decrements the reference
> count.
>

It isn't already there, because unfortunately, in general, this doesn't
work. You need the reference count to increase when the shared pointer is
copied, for example. I am of the opinion that this isn't a problem we should
solve. Inherently mixing lifetime idioms on a single object instance is
dangerous. Interoperation with shared_ptr does not make semantic sense. The
only working scenario I can imagine is one where the shared_ptr would behave
exactly like the intrusive_ptr. As others have indicated this would increase
the memory footprint of shared_ptr since any customisable functor for the
reference count increment / decrement would need to a have a reference to
the count.

Hence I have yet to see a convincing case where the design of such
interoperation would be the optimal design, and the implementation overhead
does not obey the zero overhead principle.


> Uli
>

Regards,
Neil Groves
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Re: intrusive_ptr design question

by Ulrich Eckhardt-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

On Wednesday 08 July 2009 21:33:50 Neil Groves wrote:

> On Wed, Jul 8, 2009 at 8:21 PM, Ulrich Eckhardt <doomster@...> wrote:
> > On Monday 06 July 2009 17:23:41 Zachary Turner wrote:
> > > Is there a case to be made for a more flexible shared_ptr (either
> > > through modification or through a new class addition) that allows
> > > one to provide custom reference counting semantics much the same way
> > > that shared_ptr allows one to provide custom deletion semantics?
> >
> > Maybe it's already there: shared_ptr doesn't care if the passed deleter
> > actually deletes anything. If you now take an object with an existing
> > reference count, you just increment that count and pass the function that
> > decrements it as deleter function to a shared_ptr constructor. This
> > creates a parallel reference count, but it should be safe. Nothing can
> > pull the object from under the shared_ptr's feet because it holds a
> > reference. The shared_ptr doesn't destroy the object either, at most it
> > decrements the reference count.
>
> It isn't already there, because unfortunately, in general, this doesn't
> work. You need the reference count to increase when the shared pointer
> is copied, for example.

There is no "the reference count", but actually two of them. The internal
reference count of the object doesn't increase but the external one, shared by
the shared pointers. That external one counts how many shared pointers share a
single internal reference.

 // first pointer, increases internal refcount
 intrusive_ptr<InternallyRefcounted> ptr1(raw_ptr);

 // increment refcount manually
 inc_refcount(raw_ptr);
 // second pointer, living on the above manual reference
 shared_ptr<InternallyRefcounted> ptr2(raw_ptr, &dec_refcount);


Reset either of ptr1 or ptr2. For the intrusive_ptr, it would decrement the
internal reference count. For the shared_ptr, it would decrement its own
reference count and if that reaches zero, it would also decrement the object's
internal one as part of invoking the deleter.

Should work, unless I'm missing something. Also, I'm not 100% sure that this
is what the OP is actually looking for.

Uli

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
< Prev | 1 - 2 | Next >