Boost logo

Boost :

From: William Kempf (sirwillard_at_[hidden])
Date: 2000-12-05 16:37:29


--- In boost_at_[hidden], Karl Nelson <kenelson_at_e...> wrote:
> > >> Sharing just is a bigger can of
> > >> worms unless there is a compelling reason to favor it over
cloning.
> > >
> > >One of the reason I agreed with for choosing cloning. It's just
not
> > >the reason we've been debating here.
> >
> > Definitely.
> >
> > >> (Personally I prefer sharing over cloning, but I don't feel
that
> > >> it would meet the needs thus far described.)
> > >
> > >The other reason to prefer cloning is that a sharing version can
be
> > >trivially built on top of the cloning version, or shared_ptr can
be
> > >used for simplicity.
> >
> > Agreed, so that we can build from the bottom up.
>
> I should point out that shared pointer to a cloned object is not
> the same as a a pure refcounted system. Rather that trying
> to explain it a picture is worth a thousand words...

The slot class holds data that describes a function call (be it a
true function or an object/method pair) and manages the lifetime for
this data. Why, specifically, can't this data be replaced by a
callback concept that uses cloning?

> Clone system
>
> _____ ____________________
> | | |
> handle |---->| adaptor 2 |
> _____| | __________________ |
> || adaptor 1 ||
> || ________________ ||
> ||| generic_functor|||
> ||| ______________ |||
> |||| user functor ||||
> |||| ||||
> |____________________|
>
> The object pointed to by the handle is composite of all the objects.

Makes sense.
 
> shared pointer to cloned object..
> _____
> |--------------------------------> counter
> | ____________________
> smart | | |
> ptr |---->| adaptor 2 |
> _____| | __________________ |
> || adaptor 1 ||
> || ________________ ||
> ||| generic_functor|||
> ||| ______________ |||
> |||| user functor ||||
> |||| ||||
> |____________________|

This isn't what is meant at all. The smart pointer would be an
implementation detail within generic_functor in your picture above.
 
> Pure counter system
> _______ _______ _______ _________________
> | | | | | | |
> handle |-->| adp 1 |-->| adp 2 |-->| generic_functor |
> _______| |(count)| |(count)| | (counter) |
> |_______| |_______| | _______________ |
> || user functor ||
> |_________________|

I'm not sure why this design got "flattened". It's the same as the
previous design, just with the counter as a part of generic_functor
instead of seperated.
 
> In other words, I don't think you could get a counted
> system from uncounted system. And thus since
> as multicast system is inevitably a counted system
> you can't build up.

Even ignoring the mistake in your placement of the smart pointer in
the diagram, I don't see what makes you come to this conclusion from
them. I'm missing something.

> The best you can do is build a good self contained system
> to solve a select set of problems. Then build a second system
> to solve different set of problems and describe a reasonable
> set of interaction between the two.

I also don't follow what you mean here.
 
> Similarly, I showed earlier that you can't build a system
> which takes a functor from a system which does not track
> dependencies and create the dependencies. (William agree or
> gave up in frustration when we discussed this a few weeks ago.)

When you have an object/method pair that comprises the callback you
can't know when the object is deleted with out intrusive measures on
the object. This doesn't preclude you from building the library
using the more basic callback, though efficiency may lead you to
starting from scratch here.
 
> If you were to allow it you could do this....
>
> functor<void,int> f= functor_from_method( object,
&Object::method);
> slot<void,int> sl=f;
>
> Unless you pierce the f to get the object from which the functor
> was made you can't add the dependency for the slot to track.

The slot can still be created only through the "approved" factory
functions (which would preclude creation from generic function
objects). Internally the generated function object could be based on
the basic cloning callback, with extra plumbing to hook into
destruction of objects associated with member functions. Trivial to
implement, just not necessarily the best implementation.

I'm not 100% convinced of the need to track the object's lifetime. I
think it's simpler, even as the end user, to leave this management up
to the programmer. However, I fully understand that this may be an
opinion that is very much in the minority, and understand that
there's significant users of sigc++ that would not stand for this.
This is another reason why the concepts should be seperate. Whether
they share any implementation is, frankly, a non-issue to me. It's
very possible for them to do so, but there may be compelling reasons
not to, such as efficiency.

What's important to me is that a ref-counted variant *can* be
implemented on top of the cloning variant, which could be very
important for several concepts that we've not thought of yet.

Bill Kempf


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