|
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