Boost logo

Boost Users :

From: Ovanes Markarian (om_boost_at_[hidden])
Date: 2007-06-21 14:52:19


In your case I would suggest using a Visitor pattern. You can use boost::variant to contain all
possible events and query the stored one by applying a visitor to a variant. The Variant visitor
can be a template function which will offer you the type safety and you could do casting to the
correct type...

This might look like:

typedef boost::variant<event1, event2, event3, event4, ...> event_container;

template<class Handler_>
struct EventDispatcher : boost::static_visitor<result_type_of_functor> //result can be void
{
    EventDispatcher(Handler_& h)
        : handler_(h){}

    template<class EventType_>
    result_type_of_functor operator()(EventType_ const& ev)const
    {
        return handler_.processEvent(ev);
    }

  private:
    mutable Handler_& handler_;
}

template<class Derived_>
class MostDerivedHelper
{
      ....
      void dispatchEvent(event_container* container)
     {
         // Do dispatching here
         boost::apply_visitor(container, EventDispatcher(*derived));
         //apply visitor returns the result specified as static_visitor param

     }

  private:
     Derived_* derived_;
};

I think this approach should work. And is probably has better performance as boost::bind.

With Kind Regards,

Ovanes Markarian

On Thu, June 21, 2007 19:56, Lukasz wrote:
>
> Hello,
>
> I'm fairly new to boost and don't know all of the functionality. I have been
> using the serialization library, read about mpl, signals and that's about
> it. Maybe someone will have an idea if there is anything in boost that i
> could use to solve the following problem (or any other solution).
>
> I'm working a an Agent framework, and at this point, specifically on an
> event (messaging system). The basic layout is the following (what concerns
> the messaging part):
>
> The framework contains Agents and Behaviors. They all need to communicate
> with each other. Both of these classes derive from an interface
> EventReceiver, which declares, amongst other things, a pure virtual
> ProcessEvent(Event * event) function. Specific behaviors and agents are
> obviously derived from the base ones. All events are derived from the base
> Event class (to allow users to create their own events with whatever
> information they need in there). The main messaging hub is a class
> MessengerService, which contains two maps, the first one relates static
> UUID's of events to UUID's of receivers , and the second receiver UUID's
> with a list of actual events of type Event*. The basic use case is: a
> behavior calls a register function in MessengerService to add itself as a
> receiver for a certain type of event (register/unregister can happen at
> anytime). At anytime, a behavior/agent can create an event, and call a send
> function, which adds it to the list of events that are pending for a given
> receiver (if a receiver was registered for this event type). As all
> agents/behaviors are ticked, a "Monitor" is moved to the current
> agent/behavior. The monitor queries the messenger service for all pending
> events destined for the current agent/behavior, and calls a processEvent
> function on the agent/behavior passing it the event as an argument. The
> problem is here. I want agents/behaviors to add handlers for different event
> types that they registered for, i.e.
>
> class SomeBehavior: public Behavior
> {
> ...
> processEvent(EventTest1 & event);
> processEvent(EventTest2 & event);
> ...
> }
>
> Since the events were registered, i know that the correct handlers exist in
> the most derived class types (there will also be a forwarding scheme for
> unregistered or broadcast events). The problem is that i only have a pointer
> to the base class (EventReceiver) and to the base class of the event
> (Event). I can't cast directly because i don't know the type to cast to.
> Also, i don't want to add virtual functions for all possible events to the
> base class, because that would mean that users would have to play around in
> the base class (framework) every time they add a new event. Lastly, i wanted
> to avoid having a general processEvent(Event & event) function and then have
> the users "switch" on the event type. I solved part of the problem (the
> first half) by adding a "MostDerviedHelper", which looks sort of like this:
>
> template<class Derived>
> class MostDerivedHelper
> {
> ....
> void dispatchEvent(Event * event)
> {
> // Do dispatching here
> m_derivedPointer->processEvent(*(event->This()));
>
> }
>
> private:
> Derived * m_derivedPointer;
> }
>
> Each derived type has a helper, which obviously contains the correct most
> derived type (since it's itself). The problem now, is that i don't know what
> to cast the event to so that it calls the correct handler. I can't add the
> same type of helper to event, because then i would have to pass it the
> receiver derived type through a template, but since it would have to be a
> template, i can't call it using my base class event pointer (can't create
> templated virtual functions). I tried adding a virtual function called
> "This()" to all events, which would return the derived classes' this
> pointer, but eventhough it's the correct type, i still need to cast it
> (which i can't) since it has to be resolved at compile time. I read quite a
> few things about double/multiple dispatch (in Loki for example), but it's
> not quite the solution i'm looking for because a usual implementation uses a
> callback, and that would require that i make my handlers static. MPL is not
> much of a help either because it's based on static polymorphism, and what i
> actually need is dynamic. I thought of using boost function & boost bind
> combined with a double dispatch scheme, but this doesn't work either because
> then i can't serialize it (i could re-perform the binding after a restore,
> which i already do for boost::signals, but it's a hassle). So, i'm pretty
> much out of ideas. I think to sum it up, what i would sort of need is:
>
> template<class ReceiverType, class EventType>
> class Dispatcher
> {
> ...
> send(ReceiverType * receiver, eventType * event)
> {
> receiver->processEvent(event);
> }
> }
>
> In this situation, i would already have all the correct types. The problem
> is that i can't get all this info at the same time.
>
> I also thought about using the curiously recurring template pattern as such:
>
> template<class Derived>
> class Event
> {
> template<class derivedReceiver>
> dispatch(derivedReceiver, Derived event) { .... }
> }
>
> This would work, except that since all events now must specialize to some
> type of base, i can't use a base class pointer to store in my map, i.e. i
> can't store all of my events in a map.
>
> If anyone has some brilliant idea as to how this can be done (if it can),
> then i would appreciate the input.
>
> Thanks,
>
> Lukasz
> --
> View this message in context:
> http://www.nabble.com/problem...-maybe-boost-could-help-tf3959613.html#a11235990
> Sent from the Boost - Users mailing list archive at Nabble.com.
>
> _______________________________________________
> Boost-users mailing list
> Boost-users_at_[hidden]
> http://lists.boost.org/mailman/listinfo.cgi/boost-users
>


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net