Listener-Registry Pattern implementation

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

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

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
participants (2)
-
Dean Michael C. Berris
-
Rene Rivera