# Problems with my Event handling

## Recommended Posts

Hi all, I have not long got my event system working, it's based on the article: http://www.gamedev.net/reference/programming/features/effeventcpp/ However I have hit a brick wall in relation to hasEventListener and removeEventListener features. Basically any object can extend the EventDispatcher class which gives it the ability to store a multimap of <string eventType> -> <member function>. When you call the method disaptchEvent(Event e) on this object, it does a find in the multi map for all listeners listening for Event e and calls their respective member functions. So far so good. The problem is when you try to query that multi map or remove from it. I want to be able to do something like hasEventListener("mouseOver", PanelClass, &PanelClass::handleEvent), which returns true if that specific element exists within the multi map (both key AND value pair). I also want to do removeEentListener(...same params) which removes a specific key value pair. Ok, so why not iterate through the list (or use find) and check the key and value is equal to parameters..... This is what I thought I would do. However the value is stored as a wrapped up HandlerFunctionBase object, which only knows how to do execute(). There is no getMemberFunction() or getInstanceObject() and I cant add these because the whole point of it being a wrapper is to wrap the specific object types away. Ok enough abstract stuff, ill post the code for a clearer view: Note: Ive removed destructor, constructors, includes and header guards. The commented out code is how I thought about achieving this. However HandlerFunctionBase has no getMemberFunction()... EventDispatcher.h
class EventDispatcher
{
public:
template <typename ObjectT, typename EventT>
void addEventListener(std::string a_EventType, ObjectT* a_Instance, void (ObjectT::*a_pMemberFunction)(const EventT*))
{
m_Listeners.insert(std::pair<std::string,HandlerFunctionBase*>(a_EventType,new MemberFunctionHandler<ObjectT, const EventT>(a_Instance, a_pMemberFunction)));
}

template <typename ObjectT, typename EventT>
void removeEventListener(std::string a_EventType, ObjectT* a_Instance, void (ObjectT::*a_pMemberFunction)(const EventT*))
{
/*std::pair<std::multimap<std::string, HandlerFunctionBase*>::const_iterator, std::multimap<std::string, HandlerFunctionBase*>::const_iterator> bound = m_Listeners.equal_range(a_EventType);
std::multimap<std::string, HandlerFunctionBase*>::const_iterator it;

for (it=bound.first; it!=bound.second; ++it)
{
if((*it).second->getMemberFunction() == a_pMemberFunction)
{
m_Listeners.erase(it);
bound = m_Listeners.equal_range(a_EventType);
}
}*/
}

template <typename ObjectT, typename EventT>
bool hasEventListener(std::string a_EventType, ObjectT* a_Instance, void (ObjectT::*a_pMemberFunction)(const EventT*))
{
bool hasListener = false;
/*std::pair<std::multimap<std::string, HandlerFunctionBase*>::const_iterator, std::multimap<std::string, HandlerFunctionBase*>::const_iterator> bound = m_Listeners.equal_range(a_EventType);
std::multimap<std::string, HandlerFunctionBase*>::const_iterator it;

for (it=bound.first; it!=bound.second; ++it)
{
if((*it).second->getMemberFunction() == a_pMemberFunction)
{
hasListener = true;
break;
}
}*/

return hasListener;
}

virtual void dispatchEvent(Event* a_Event);

private:
std::multimap<std::string, HandlerFunctionBase*> m_Listeners;
};


EventDispatcher.cpp

void EventDispatcher::dispatchEvent(Event* a_Event)
{

std::string eventType = a_Event->getType();
std::pair<std::multimap<std::string, HandlerFunctionBase*>::const_iterator, std::multimap<std::string, HandlerFunctionBase*>::const_iterator> bound = m_Listeners.equal_range(eventType);
std::multimap<std::string, HandlerFunctionBase*>::const_iterator it;

for (it=bound.first; it!=bound.second; ++it)
{
(*it).second->execute(a_Event);
bound = m_Listeners.equal_range(eventType);
}
}


HandlerFunctionBase.h
class HandlerFunctionBase
{
public:

void execute(const Event* a_Event)
{
call(a_Event);
}
private:
virtual void call(const Event* a_Event) = 0;
};


MemberFunctionHandler.h
template <typename ObjectT, typename EventT>
class MemberFunctionHandler : public HandlerFunctionBase
{
public:
typedef void (ObjectT::*MemberFunction)(const EventT*);

MemberFunctionHandler(ObjectT* a_Instance, MemberFunction a_MemberFunction):
m_Instance(a_Instance), m_MemberFunction(a_MemberFunction) {};

void call(const Event* a_Event)
{
(m_Instance->*m_MemberFunction)(static_cast<EventT*>(a_Event));
}

private:
ObjectT* m_Instance;
MemberFunction m_MemberFunction;
};


Should I just dynamic cast the HandlerFunctionBase to MemberFunctionHandler and add the getMemberFunction() to that? Or is there a better solution? Also feel free to critique the code/style/my life in general. Thanks! Aaron

##### Share on other sites
No ideas?

A solution that doesn't involve casting could be to use covariants. So in the base class I could add:

HandlerFunctionBase.h
virtual HandlerFunctionBase* getFunctionHandler() = 0;

MemberFunctionHandler.h
virtual MemberFunctionHandler* getFunctionHandler() {return this;}MemberFunction getMemberFunction() {return m_MemberFunction;}

So to get the wrapped up member function I could use:

MemberFunctionHandler* mfh = (*it).second->getMemberFunctionHandler();

Is covariants ok to use in this situation? Or should I go with dynamic_cast? Or does anybody want to step up to the plate and lay down a better solution?

Thanks

Aaron

##### Share on other sites
The above didn't work out too well, because of the templates things started getting a bit messy.

So ive got it working using dynamic_cast:

MemberFunctionHandler<ObjectT, const EventT>* mfh = dynamic_cast<MemberFunctionHandler<ObjectT, const EventT>*>((*it).second);

Its only called when querying for an event listener or removing one, I dont think that would be very often so I'm ok with the performance loss. Is there any other reason I shouldn't be doing the dynamic_cast? Could I possibly make that a static_cast instead?

Feel free to comment on the design

Thanks