Listener-Registry Pattern implementation

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Listener-Registry Pattern implementation

Dean Michael Berris-2
Good day everyone,

I have just uploaded a simple implementation to the vault of my proposed
listener-registry pattern implementation. Let me explain how this is
different from Boost.Signals:

1) It doesn't use MPL (yet) -- since because the pattern is quite
simple, I have implemented it such that the listener class should be
inherited, and a handle() method should be overridden by the specific
listeners. This would change, once I start learning more about MPL --
which should make the implementation more flexible at compile time.

2) It maps inputs to processors, while Boost.Signals allows you to use a
signal which maps to different slots (which are all called in turn, once
the signal is invoked). The listener-registry pattern implementation
defines a registry to which listeners register themselves -- the
registry then does the routing of inputs to the listeners. Think event
driven processing, where a listener listens for a specific event and is
invoked only when the specific input is passed into the registry which
it is registered to.

3) It currently only intends to receive a single input type, which
should change as I learn more about the MPL and how to make it more
extensible with regards to compile time specification.

The file is up at the vault (listener.tar.gz) and unfortunately, I chose
to use the CppUnit test framework, and the GNU Make build system -- I've
tried it on Ubuntu Linux 5.10, and requires libcppunit to build the test
case.

Comments, suggestions, and pointers most appreciated.

Thanks, and hope to hear from you guys soon.

--
Dean Michael C. Berris
Mobile +639287291459
URL http://mikhailberis.blogspot.com
YMID: mikhailberis

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Listener-Registry Pattern implementation

Rene Rivera
Dean Michael C. Berris wrote:
> Good day everyone,
>
> I have just uploaded a simple implementation to the vault of my proposed
> listener-registry pattern implementation.

Hm, doesn't seem to be much there, and hence it's hard to comment on it.
A little bit of explanatory documentation would go a long way ;-)

> Let me explain how this is
> different from Boost.Signals:
>
> 1) It doesn't use MPL (yet) -- since because the pattern is quite
> simple, I have implemented it such that the listener class should be
> inherited, and a handle() method should be overridden by the specific
> listeners. This would change, once I start learning more about MPL --
> which should make the implementation more flexible at compile time.

Change into what?

> 2) It maps inputs to processors, while Boost.Signals allows you to use a
> signal which maps to different slots (which are all called in turn, once
> the signal is invoked). The listener-registry pattern implementation
> defines a registry to which listeners register themselves -- the
> registry then does the routing of inputs to the listeners. Think event
> driven processing, where a listener listens for a specific event and is
> invoked only when the specific input is passed into the registry which
> it is registered to.

Over the past few weeks I've been implementing something basically like
that for a model-view-* system. And as I understand your goals, does
what you want. That is, it does signal to call dispatching from many
sources to many endpoints through a single router/dispatcher. To give
you some idea the signal points would look like:

reflection->Signal(signal::Resize((width = 20, height = 30)));

The registration of endpoints like:

void handle_resize(Window * window, int w, int h);

*reflection << MakeReflector<Resize>((
   signal = boost::bind(&handle_resize, my_window, _1, _2) ));

Types are enforced at compile time, all around, even though the
implementation uses boost::any for it's safe type erasure. There's some
other type definitions involved to make the above possible of course ;-)

> The file is up at the vault (listener.tar.gz) and unfortunately, I chose
> to use the CppUnit test framework, and the GNU Make build system -- I've
> tried it on Ubuntu Linux 5.10, and requires libcppunit to build the test
> case.

Kinda limits how many people will give you feedback :-\



--
-- Grafik - Don't Assume Anything
-- Redshift Software, Inc. - http://redshift-software.com
-- rrivera/acm.org - grafik/redshift-software.com
-- 102708583/icq - grafikrobot/aim - grafikrobot/yahoo
_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
Reply | Threaded
Open this post in threaded view
|

Re: Listener-Registry Pattern implementation

Dean Michael Berris-2
On Fri, 2006-03-03 at 01:30 -0600, Rene Rivera wrote:
> >
> > I have just uploaded a simple implementation to the vault of my proposed
> > listener-registry pattern implementation.
>
> Hm, doesn't seem to be much there, and hence it's hard to comment on it.
> A little bit of explanatory documentation would go a long way ;-)
>

Thanks. It never really crossed my mind to write some simple
documentation regarding it. I should come up with something in a short
while. :)

> > 1) It doesn't use MPL (yet) -- since because the pattern is quite
> > simple, I have implemented it such that the listener class should be
> > inherited, and a handle() method should be overridden by the specific
> > listeners. This would change, once I start learning more about MPL --
> > which should make the implementation more flexible at compile time.
>
> Change into what?
>

The current implementation requires that a method named handle() be
defined which takes in a const reference to a user-defined type. This is
severely limiting, and does not fit well with the STL style of
overriding operator() () to provide functor functionality.

For instance, I would like to be able to do something like this:

struct my_registry : public listener_registry<int, (double, double)> {
        ...
};

static my_registry global_dispatcher;

struct my_listener1 : public listener<int, (double, double)> {
        my_listener1() : listener(global_dispatcher, 1);
        ...
        int operator() (double a, double b) {
                return do_some_processing(a, b);
        }
        ...
};

struct my_listener2 : public listener<int, (double, double)> {
        my_listener2() : listener(global_dispatcher, 1);
        ...
        int operator() (double a, double b) {
                return do_some_other_processing(a, b);
        }
        ...
};

And maybe perhaps simplify it by creating the listeners during compile
time, and just bind them to methods. I don't know if that's possible: to
make named types during compile time using template metaprogramming
techniques, but as I learn more and more about Boost.MPL everyday, I
sure hope it will let me do that.

My goal really is to be able to do the following:

struct my_functor {
        int operator() (double a, double b) {
                return 1;
        }
};

struct my_listener1 : public listener<int (double, double),
        /* to bind to signal */ 1,
        /* functor type name */ my_functor> {
        my_listener1 : listener(global_dispatcher, my_functor()) { };
        ...
};

Or maybe even:

struct my_functor {
        ...
};

GENERATE_LISTENER(my_listener1, (int (double, double)), 1, my_functor);
GENERATE_LISTENER(my_listener2, (int (double, double)), 2, \
        my_other_functor);

Using some major preprocessor magic.

> > 2) It maps inputs to processors, while Boost.Signals allows you to use a
> > signal which maps to different slots (which are all called in turn, once
> > the signal is invoked). The listener-registry pattern implementation
> > defines a registry to which listeners register themselves -- the
> > registry then does the routing of inputs to the listeners. Think event
> > driven processing, where a listener listens for a specific event and is
> > invoked only when the specific input is passed into the registry which
> > it is registered to.
>
> Over the past few weeks I've been implementing something basically like
> that for a model-view-* system. And as I understand your goals, does
> what you want. That is, it does signal to call dispatching from many
> sources to many endpoints through a single router/dispatcher. To give
> you some idea the signal points would look like:
>
> reflection->Signal(signal::Resize((width = 20, height = 30)));
>
> The registration of endpoints like:
>
> void handle_resize(Window * window, int w, int h);
>
> *reflection << MakeReflector<Resize>((
>    signal = boost::bind(&handle_resize, my_window, _1, _2) ));
>
> Types are enforced at compile time, all around, even though the
> implementation uses boost::any for it's safe type erasure. There's some
> other type definitions involved to make the above possible of course ;-)
>

Basically that's essentially what I've been trying to do, and have been
having a hard time making generic. I have been encountering a lot of
problem domains where the handling of inputs change from time to time,
and routing rules are better implemented in a single component than many
different cascading components/class hierarchies.

> > The file is up at the vault (listener.tar.gz) and unfortunately, I chose
> > to use the CppUnit test framework, and the GNU Make build system -- I've
> > tried it on Ubuntu Linux 5.10, and requires libcppunit to build the test
> > case.
>
> Kinda limits how many people will give you feedback :-\
>

Yeah. I also need to learn the Boost testing framework, and learn Bjam
for the build process.

Too much stuff to learn in so little  time... :)

--
Dean Michael C. Berris
Mobile +639287291459
URL http://mikhailberis.blogspot.com
YMID: mikhailberis

_______________________________________________
Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost