Boost logo

Boost :

From: Greg Colvin (gcolvin_at_[hidden])
Date: 2001-09-03 23:51:53


From: David Abrahams <david.abrahams_at_[hidden]>
> From: "Greg Colvin" <gcolvin_at_[hidden]>
>
> > It seems that by adding one constructor to shared_ptr and shared_array
> > we could satisfy Dave's needs:
> >
> > shared_ptr::shared_ptr(
> > T* object, shared_counter_base* counter=shared_ptr_counter);
> >
> > shared_array:shared_array(
> > T* array, shared_counter_base* counter=shared_array_counter);
> >
> > Where shared_counter_base is something like:
> >
> > class shared_counter_base {
> > protected:
> > long count;
> > void* object;
> > void (*destroy)(void*);
> > public:
> > shared_counter_base(): count(0),object(0),destroy(0) {}
> > void increment() { ++count; }
> > void decrement() {
> > if (!--count)
> > assert(destroy), destroy(object);
> > }
> > };
> >
> > It is the job of the destroy function to release storage for the
> > shared object and itself when the count goes to zero. I use a
> > pointer-function rather than a virtual destructor so as safe a
> > smidgen of time and so as not to forclose options for how the
> > counter is allocated.
> >
> > Then Dave can derive his own counter class and arrange for his array
> > allocator to stash the counter at the head of his array.
> >
> > Whether this is easier to do than to write his own class I can't say.
> > It would be a slightly larger header than needed for a custom
> > implementation. One advantage to this approach, if it matters, is
> > that the rest of Dave's code can traffic in shared_array without
> > caring about the array allocator.
>
> Does this approach require storing a separate pointer to the counter in the
> shared pointer?

Yes.

> That's something I don't want to pay for.

Hmmm. I know how to fix that, but there will be other tradeoffs
to achieve that. The fix is to switch to an indirect strategy,
with only one raw pointer in the

So you may well need to roll your own.

> Taking a step back, we can come up with any number of designs, but shouldn't
> we talk about what the designs should accomplish first?

We have been, but further discussion is welcome.

What I'm not trying to accomplish is to parameterize shared_ptr to
generate a large family of related classes. That is a bigger project
that should probably start fresh, and which will indeed require a
clear delineation of a family of Pointer concepts.

What I am trying to do is pull together the discussions and experimental
code and feature requests built up over the years into a new version of
shared_ptr (and shared_array). The desiderata for me are:

1) Shared_ptr remains one class, with one interface and one semantics.
   Libraries should be able to use shared_ptr as a common means of
   communication without needing to templatize their interfaces by
   (smart) pointer type.

2) It should be possible for users to easily customize the deletion
   function for objects that are not created with operator new. For
   example the many, many C interfaces that manage resouces with a pair
   of pointer-returning functions for acquistion and release. Peter's
   code has an implementation of this idea.

3) It should be possible to use shared_ptr with no risk of undefined
   behavior, although for historical reasons some unsafe functions may
   remain, such as construction and reset from raw pointers. These
   functions proven to be a source of difficulty and error. Right
   now I am leaning towards a static create() function with varying
   numbers of parameters, initially faked with a large number of
   create functions, but perhaps done right in the future with a
   language extension.

4) It should be possible for the skilled user to modify the underlying
   implementation to make some performance and safety trade-offs
   with out affecting the interface. The current idea is to expose
   the underlying counter object for customization, but it isn't
   clear whether that will prove useful enough to be worth the price.

I am also aware of the need, over the next year, to get a version of
shared_ptr ready for the C++ committee. So it is important to keep
the interface clean, and the design such that the more advanced
features can be dropped or modified by the committee without disturbing
the core functionality. In particular, doing (4) will probably reveal
more implementation detail than is appropriate for a standard class.
   


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk