Boost logo

Boost :

From: Douglas Gregor (gregod_at_[hidden])
Date: 2000-11-17 15:26:55


On Fri, 17 Nov 2000 19:40:05 -0000
"William Kempf" <sirwillard_at_[hidden]> wrote:

> > I've written a small library
> > (http://www.cs.rpi.edu/~gregod/blackrock/blackrock-0.2.1.tar.gz)
> > which already fulfills all requirements except for #3 (due to
> > memory allocations in the copy). I'll Boostify and submit it if
> > there is sufficient interest. In the library, I referred to
> > callback as "events", so consider the terms interchangeable for now
> > and I would happily change the terminology during Boostification.
> > Now to a library usage summary:
>
> Thanks. It will take me a while to evaluate this because of the
> amount of code involved (mostly repetition because of the number of
> parameters acceptable). The code I posted is easier to decipher, so
> if you've got time you might help everyone out by detailing what you
> see the differences as. I'll take a crack at what was obvious to me:

See below.
 
> Both implementations use the Bridge pattern to achieve External
> Polymorphism. However, your implementation both derives from and
> includes a pointer to a "base/impl" class. I'm not sure this is
> needed, or even necessarily a good idea.

It is a holdover from my initial thoughts on the implementation of a "MultiEvent" class (any number of targets, the results of which are combined via another event), though it is not necessary now that Event inherits EventBase. I can remove this inheritance link, but Event will remain statically polymorphic with EventBase.

> Your implementation uses the Clone pattern to implement copy and
> assignment. This is what results in your implementation not
> fullfilling requirement #3. My/Jesse's implementation uses a
> reference counting mechanism instead (in fact the working
> implementation I've currently got in Threads uses a hacked version of
> boost::shared_ptr which is thread safe). For efficiency reasons I
> think this is the better implementation, but right now I'm also
> wondering if this might cause some unforseen issues as well.

I agree that it is better to use a reference-counted pointer for efficiency reasons.
 
> Your implementation uses a single class for "callbacks" with some
> template arguments defaulted to a utility Unused class. This is a
> similar idea to how tuples are implemented and is worth considering
> as an alternative to multiple class definitions for callbacks of
> different numbers of arguments.

(Opinion warning:)I found this to be more natural from a user's perspective because it does not require duplication of information (if I supply 3 arguments, why do I also have to use Callback3?).
 
> That's the obvious stuff I see. Care to provide a better comparison
> summary?

Of course. Here is a summary of the differences I see so far (including those pointed out above):

1) I use one "Callback" class that takes any number of parameters
  instead of having many Callback0, Callback1, ..., CallbackN
  classes.

2) I provide a conversion to bool so that we can check if a given
  callback has a target. This allows us to more easily create
  functions where an outside user can (optionally) change some
  behavior of the function at runtime. For instance, we may want
  a system where the user can change (at runtime) the computation
  of the norm of two vectors within some algorithm. Then we can
  define a callback:
        Callback< float, Vector<float>, Vector<float> >
          calculateNorm;

  // Then, when we need the norm
  float norm; Vector<float> u, v;
  if (calculateNorm)
    norm = calculateNorm(u,v); // user calculates the norm
  else
    norm = innerprod(u,v); // Default to the inner product

3) I have explicit classes (each derived from EventBase) which
  allow callbacks to member functions, free functions or
  functors. It appears that the William Kempf and Jesse Jones'
  solution would use only functors (relying on another library
  (the lambda library?) to build functors out of free/member
  functions). This makes it tougher to include the bool
  conversion (how do we know if a functor has a real target or
  not?), which I consider essential.

4) I provide an "event" helper function which builds an
  appropriate event object given the operands. Granted, this is
  not very useful if #3 isn't considered useful.
  

        Doug Gregor
        gregod_at_[hidden]


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