Boost logo

Boost :

From: William Kempf (sirwillard_at_[hidden])
Date: 2000-11-19 10:45:31


--- In boost_at_[hidden], Karl Nelson <kenelson_at_e...> wrote:
> > > Hopefully, once sigc++ is simplified and made threadsafe I will
> > > submit it. Currently, I consider the code base too young
> > > to be ready for standardization.
> >
> > Ok, then I'll start to address the issues I see in libsigc++ over
> > what we've been discussing.
>
> > First, libsigc++ is really a Signal/Slot implementation which
isn't
> > quite the same thing as a callback. Signals/Slots are really a
multi-
> > casting concept based on callbacks. The thread library isn't
really
> > appropriate for Signals/Slots while it's very appropriate for
> > callbacks. I'd prefer to see the simpler Concept of Callback
fleshed
> > out and implemented after which the Signal/Slot can be built on
top
> > (or, if efficiency suggests so the implementation may be built
> > totally on it's own... it's just a seperate and distinct Concept
to
> > me).
>
> Okay 3 issues here...
>
> 1) Should a library have a callback and later build slots?
> I have had that arguement a number of times and what always gets
pointed
> out is that building just callbacks causes some many problems
> it isn't worth it. Libsigc++ provided the class Callback# which
> was exactly that. It was a union of pointers, function pointers,
> methods with objects etc. However, as I discovered you
> would have to build your own set of factories for those callbacks
> in effect doubling the size of the library.

That's what libraries like Lambda are for.

> Second, you can't
> really build adaptors with the callbacks because they would
> require chaining of resources. In other words, slots
> in the clean up capablity allow cleaning up the objects which
> allow adaptors. So Callbacks are of limited use.

I *really* don't follow this. Care to post some specific examples of
what you mean?

> Further,
> they aren't all that useful to build the Slots themselves as
> the slot just ends up carrying arround the bulk of
> a general callback where it could be trimmed down.

I'm not suggesting that Slots have to be built off of a general
callback, just that it would be worth considering once done. As
for "bulk"... we're talking a virtual table, a pointer and the size
of the functor. A Slot must carry at least this any way. I don't
see problems with bulk.
 
> 2) Can a Slot be a Callback?
> The answer to this is yes. That is that if I make a Slot like
> concept with the ablity to disconnect and clean up the
> traces between objects, I don't have to use that path.
> Thus it is a very common misunderstanding the to use SigC
> you must use SigC::Object. You don't, you simply must use a
different
> factory to produce pure callbacks rather than slots. Thus
> nothing in SigC requires SigC::Object other than SigC internals.

But Signals/Slots are multi-casting concepts, which is *not* the same
as a callback. Or are you suggesting that the Slot by itself is a
pure callback? If so, the documentation in libsigc++ doesn't address
this at all, which is a huge disservice. Callbacks are frequently
needed in areas in which a multi-casting Signal/Slot is either
overkill or even problematic.

> 3) Can a Signal/Slot be used in Threads?
> There are issues but they aren't as bad as they first appear.
> Ther real problem is that only one thread can be destroying or
> adding things to a list at one time. Some of this
> can be done properly with make before break and atomic flags on
> the lists. Further, the reference counters have to be protected.
> Really advanced adaptors and signals are out unless the signal
> queue is protected internally. But for the most part it
> is doable.

I never suggested it wasn't ;). The Boost thread library (which is
far from ready for prime time) could be quite useful for insuring
thread safety here.
 
> So what is a Slot exactly
> - Acts as a callback
> - Can clean up if the target is removed
> - Can clean up if the source is removed
> - String-like construction (pointer to a functor which can be
shared
> copied and manipulated)
>
> A bound pointer (Borlands pure callback idea) lacks the 3rd
property
> and thus can't be used as adaptors. Many callback systems lack
2nd.

If I follow you here, this is a take on safety that goes beyond what
I considered necessary, but it's valuable none-the-less. Worth
thinking about.

> Okay so you quickly think why can't I just add a list in the
> the object the callback is pointed to to kill the callback and
> make a slot? But that creates its own problem, who cleans up
> the list if the callback goes away? Basically you end up with
> dependency loops, which require a unified method to handle the
> internal cleanups. Adaptors to callbacks also cause this
> dependency loop because the data in the adaptor can become stale.
> Thus for efficency building a really good Signal/Slot library
> which has the ablitity to do the event and threading is
> the right approach.

I still have problems with the multi-cast issue. If you can address
that to my satisfaction I'll have a better idea of where you're
coming from.
 
> > Third, use of a slot() generator appears to just be reduplication
of
> > effort better handled by Lambda and other functor libraries.
(Note,
> > this too may be an unfair criticism. Doug's event() method is no
> > different. It may be advantageous to have two such generators,
one
> > to generate simple callbacks and the other to generate the
callbacks
> > with additional functionality required for Signal/Slot useage.
This
> > idea would require serious thought, however, to insure type
safety
> > and compatibility.)
>
> Well, signal/slots are always going to require their own generators
> as to get the unregistering capablity you must form both the
> bound pointer and make the dtor mechanism to clean up.

But such a factory could be simplified by using Lambda or other
binding libraries. If the factory needed only a simple functor to
generate the "slot" things would be greatly simplified, no?
 
> > These are preliminary thoughts. I'll have to take a much closer
look
> > at libsigc++ now. I'd be very interested in hearing your
thoughts on
> > this. If we can come to some consensus here I may be of help to
you
> > in adding thread safety to libsigc++ and in submitting the
library to
> > Boost.
>
> I won't look at libsigc++ TOO closely, because there was a lot
> of crap there which I quite frankly and throwing out.
>
> Things that are going... Handles, Scopes, Callback#. These
> were attempts to make a unified type ie a Slot was a Object
> etc. These bad attempts are going away. The reduced library is
> a fraction of the size. Further I am paring out the
> use of some memory elements. Thus the cost of an object slot
> is going from 64 bytes to 28 and so on.
>
> With luck the cost of a good slot system will be almost the
> same as the cost of a good callback system.

Any work in progress we can look at? I realize you're time is
limited, but the need for callbacks in Boost is great enough to
generate some urgency on my part. If you plan to submit the slot
system any way I'd really like to not step on your toes by pushing
for a (possibly) competing callback system.

Bill Kempf


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