I am currently programming an event passing system for a game in C++ and I thought it would be useful if the events inherited from each other in a logical way.
This means I could for example raise an event of type NukeExplosion, which derives from Explosion (which would probably derive from an empty base class Event) and it would get passed to all listeners to an event of type NukeExplosion, as well as the more generic Explosion.
So far I was able to come up with two possible solutions:
Doing a dynamic_cast on the event for each set of listeners to the same event type. If it succeeds, I can then pass the event to all the listeners in the set.
Adding a piece of code to each Event type which raises the event again, but with a more generic type. The event would then be passed to listeners using the result of the typeid operator in conjunction with a map of listeners.
I don't really like the second option, because it's error-prone, and requires me to write almost the same code in every event class.
The problem with the first option is that it might need to do a lot of dynamic_casts, and I would like to avoid that.
So, is there any other way which I haven't taken into accont, or is the first option the best I can do? Or should I completely drop the inheritance of events?
I came here with almost exactly this question. The problem is basically that C++ won't let a function like handle (ExplosionEvent *e) accept an argument e with static type Event * even when the dynamic type of e is ExplosionEvent *. It would be a nice feature to have, but I'm not quite sure what else would have to change in the language.
The Visitor pattern is the cleanest solution I can think of. The drawbacks are that it's verbose and that it may not be cheaper than dynamic_cast<>.
Main.hpp:
#include <iostream>
class Event;
class Handler;
#include "Event.hpp"
#include "Handler.hpp"
Event.hpp:
#ifndef EVENT_H
#define EVENT_H
class Event
{
public:
virtual void accept (Handler *handler) { }
};
class ExplosionEvent : public Event
{
void accept (Handler *handler);
};
#endif // !EVENT_H
Event.cpp:
#include "Main.hpp"
void
ExplosionEvent::accept (Handler *handler)
{
handler->handleExplosion (this);
}
Handler.hpp:
#ifndef HANDLER_H
#define HANDLER_H
class Handler
{
public:
void handle (Event *event) { event->accept (this); }
virtual void handleExplosion (ExplosionEvent *explosionEvent) { }
};
class ExplosionHandler : public Handler
{
void handleExplosion (ExplosionEvent *explosionEvent);
};
#endif // !HANDLER_H
Handler.cpp:
#include "Main.hpp"
void
ExplosionHandler::handleExplosion (ExplosionEvent *explosionEvent)
{
std::cout << "BOOM!" << std::endl;
}
Main.cpp:
#include "Main.hpp"
int
main (int argc, char *args)
{
Event *event = new ExplosionEvent;
Handler *handler = new ExplosionHandler;
handler->handle (event);
}
Compile and run:
$ g++ -o boom *.cpp
$ ./boom
BOOM!
$
Doing a dynamic cast for every listener will get really expensive for a large number of listeners so you probably will have to implement a map of typeid to listeners anyway.
My listener would have an HandleEvent which would take an Event object. This method would cast(with a static_cast) the base event to the event type it is expecting(it needs to trust the event dispatcher for the event registering mechanism).
I would also implement a method in the Event class which would return a new base event if valid because you might not want to send a base Event. This could be done with a macro but I have a feeling it could also be done with a template method although I haven't been able to make it work yet. The dispatcher would then get that base event before calling the event handlers and then call the handlers for the base event.
Related
In my application, I have several modules that don't fit an 'is-a' or 'has-a' relationship, but still need to communicate and pass data to each other. To try and loosely couple these modules, I've implemented an Event Bus class that handles message passing from 'event posters' to 'event listeners'.
Classes can implement IEventListener if they wish to register to receive certain events. Likewise, classes can call EventBus::postEvent() if they need to push an event out to the bus. When EventBus::update() is called EventBus processes the queue of scheduled messages and routes them to registered listeners.
EventBus.h
#pragma once
#include <queue>
#include <map>
#include <set>
#include <memory>
class IEvent
{
public:
static enum EventType
{
EV_ENEMY_DIED,
EV_ENEMY_SPAWNED,
EV_GAME_OVER
};
virtual ~IEvent() {};
virtual EventType getType() const = 0;
};
class IEventListener
{
public:
virtual void handleEvent(IEvent * const e) = 0;
};
class EventBus
{
public:
EventBus() {};
~EventBus() {};
void update();
void postEvent(std::unique_ptr<IEvent> &e);
void registerListener(IEvent::EventType t, IEventListener *l);
void removeListener(IEvent::EventType t, IEventListener *l);
private:
std::queue<std::unique_ptr<IEvent>> m_eventBus;
std::map<IEvent::EventType, std::set<IEventListener *>> m_routingTable;
};
EventBus.cpp
#include "EventBus.h"
using namespace std;
/**
* Gives the EventBus a chance to dispatch and route events
* Listener callbacks will be called from here
*/
void EventBus::update()
{
while (!m_eventBus.empty())
{
// Get the next event (e_local now owns the on-heap event object)
unique_ptr<IEvent> e_local(move(m_eventBus.front()));
m_eventBus.pop();
IEvent::EventType t = e_local->getType();
auto it = m_routingTable.find(t);
if (it != m_routingTable.end())
{
for (auto l : ((*it).second))
{
l->handleEvent(e_local.get());
}
}
}
}
/**
* Posts an event to the bus, for processing and dispatch later on
* NB: The event bus will takes ownership of the on-heap event here
*/
void EventBus::postEvent(unique_ptr<IEvent> &e)
{
// The EventBus now owns the object pointed to by e
m_eventBus.push(unique_ptr<IEvent>(move(e)));
}
/**
* Registers a listener against an event type
*/
void EventBus::registerListener(IEvent::EventType t, IEventListener *l)
{
// Add this listener entry
// If the routing table doesn't have an entry for t, std::map.operator[] will add one
// If the listener is alredy registered std::set.insert() won't do anything
m_routingTable[t].insert(l);
}
/**
* Removes a listener from the event routing table
*/
void EventBus::removeListener(IEvent::EventType t, IEventListener *l)
{
// Check if an entry for event t exists
auto keyIterator = m_routingTable.find(t);
if (keyIterator != m_routingTable.end())
{
// Remove the given listener if it exists in the set
m_routingTable[t].erase(l);
}
}
As you can see, in my current implementation, I create concrete IEvent implementations for every type of event I want to pass around. I did this so that each event can have custom data attached to it (a requirement for my situation). Unfortunately, this means my EventBus system has to know about all the users of the system, increasing the coupling between my EventBus class and the users of the class. Additionally, the IEvent interface needs to hold a list of all event types as an enum, which has the same problem (increased coupling).
Is there a way to modify this implementation so that EventBus can be totally generic (doesn't need to know about the users of the EventBus), and yet still allow me to pass custom data with each event? I looked into C++11 variadic template functions but couldn't figure out how to use them in this case.
As a side-question, am I using std::unique_ptr correctly here?
Question 1 "Is there a way to modify this implementation so that EventBus can be totally generic":
Short answer, yes.
Longer answer: There are many ways of accomplishing this. One is described here:
Both the producer and the consumer of the event needs to agree on the type/data but the EventBus itself does not need to know. One way of accomplishing this could be to use boost::signals2::signal<T> as the event type. This will give you a proven, flexible and type safe signal/slot implementation. What it will not provide, however, is the possibility to queue up slot callbacks and process them from the EventBus::update()-function.
But, that can also be remedied. By making the event type EventBus::postEvent() takes as a parameter be std::function<void()> and calling postEvent() like this:
boost::signals2::signal<int> signal;
...
eventbus.postEvent(boost::bind(signal, 42));
// note: we need to use boost::bind (not std::bind) for boost::signals to be happy
The EventBus will see a std::function<void()> and dispatch to the slot. The data (42 in this example) will be kept by the result of boost::bind and be used as the parameter when the slot is called.
Question 2 "Am I using std::unique_ptr correctly":
Almost. I would drop the reference of EventBus::postEvent making it:
void EventBus::postEvent(std::unique_ptr<IEvent> e);
By doing this, you force the caller to actively move the std::unique_ptr<IEvent> into the EventBus. This will make the user aware the EventBus takes ownership and also making it obvious to people reading the code what the intent is and how ownership is transferred.
CppCoreGuidelines R.32:
"Take a unique_ptr parameter to express that a function assumes ownership of a widget"
I have a template class, in my case a state-machine class, so that I can construct it with any of my class-types such that it can call member functions using a function table with pointers to the member functions (kind of like a call-back).
It processes an event by looking the event up in a table (where state and event match) and then calling the pointer to the appropriate function.
This is all working. What I want to do next is add a timer so that when the timer expires it calls the processEvent() function with event code "TIMER_EXPIRED".
The problem for me is that in Qt template classes don't appear to be supported for slots/signals. So, I can add a QTimer, but I can't connect it up or define/emit slots/signals.
My alternative is to implement the timer in the class that owns the state machine, which is fine, but then I have to do this for all classes that use the state machine class.
So I am not really sure which direction to go next, is there some trickery I can use to get around this issue?
I would add example code, but since I have not been able to implement the QTimer within the state machine class, because I can't inherit QObject, there is no code to show yet :(
Lambdas can be utilized this way:
#pragma once
#include <QDebug>
#include <QTimer>
template< class T > class MyClass
{
public:
MyClass()
{
_timer.setInterval(1000);
// connecting the signal to the lambda
// that will call the desired function:
QObject::connect(&_timer, &QTimer::timeout,
&_timer, [&](){
theFunctionThatNeedToBeRunOnTimer();
});
_timer.start();
}
void theFunctionThatNeedToBeRunOnTimer()
{
qDebug() << "Timer ticked!";
}
private:
QTimer _timer;
};
I'm writing a C++ programm using GTK+3.0. Anyway, I think this question may apply to any framework that uses events / signals.
I have a container class, say containerClass and a child class, say childClass. A childClass object child is contained inside a containerClass object container.
The child object is written to modify properties of something. To this aim, it has GtkEntry, GtkButton and so on. When I click the "save button", an event is raised.
This event must be handled by the container object, because the container is interfaced with a database in someway.
Hereafter, you find the solution I'm using to do the job:
// Child class
class childClass {
void setClickHandler_External(void (*extFun)(string property), void *);
void (*clickHandler_External)(string, void *);
void *clickHandler_External_Data;
static void buttonClicked(GtkWidget *widget, void *data);
}
void childClass::setClickHandler_External(void (*extFun)(string), void *data) {
// Set the external event handler
clickHandler_External = extFun;
clickHandler_External_Data = data;
}
void childClass::buttonClicked(GtkWidget *widget, void *data) {
childClass *m = (childClass *)data;
// Call the external event handler
m->clickHandler_External(property, m->clickHandler_External_Data);
}
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, void *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External((void(*)(string))&(this->clickHandler), (void *)this);
}
void containerClass::clickHandler(string property, void *data) {
// Event handler in the upper class
containerClass *m = (containerClass *)data;
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
This works well and does the job. Anyway, I was wondering if there is a smarter and cleaner way to achieve the same aim, maybe without using pointers to static functions, or by defining some kind of pattern to be reused everytime I need to have the same mechanism.
Thanks in advance
Gtkmm uses the sigc++ library to take care of all of this for you. There is no need to write it yourself.
Documentation links:
Signals overview
Appendix with detailed information
So, in this case, I would use something like
button.signal_clicked().connect(sigc::mem_fun(container, &containerClass::clickHandler));
while making sure that containerClass::clickHander has the appropriate number of arguments.
My first suggestion would be to use use templates to improve the type safety of what you are doing:
template< class ParamType >
void childClass::setClickHandler_External(void (*extFun)(string, ParamType *),
ParamType *data)
{
// Set the external event handler
clickHandler_External = (void ()(string,void*))extFun;
clickHandler_External_Data = (void*)data;
}
Then you can simplify the containerClass implementation as such:
// Container Class
class containerClass {
childClass child;
static void clickHandler(string property, containerClass *data);
}
containerClass::containerClass() {
// Set the event handler
child.setClickHandler_External(&containerClass::clickHandler, this);
}
void containerClass::clickHandler(string property, containerClass *data) {
//FINALLY, DO THE JOB WITH PROPERTY!!!
}
While it's great that this cleans up the implementation, removing the explicit casting from all the container implementors, that's not really the point. The point is to prevent you from passing wrong pointers into setClickHandler_External, causing crashes on the back end when events get dispatched.
My next step would take us further from your implementation, but would require more details about what you are actually doing. Depending on your needs that would be looking into:
Inheritance: should containerClass derive from childClass? That would provide access to a virtual function table that we could override.
Functors: look at boost::function and boost::bind to implement functors, eliminating the intermediate static function call.
Lambda Functions: bleeding edge (C++11 or later), but may be a good fit for this kind of forwarding function.
I'm looking for opinions on the best OO way to accomplish what I am about to describe. I'm writing what is going to become an event system for games and the like and I want it to be as extensible as possible, as such there is a lot of abstract classes. Two of these are monitors which are assigned to monitor one event, and callbacks, which wrap the function pointer to be called should the event take place. The issue arises when I want to send the data that the callback needs. The data that will be sent is going to be sub-class specific (depending on the function signature) and stored in the subclassed monitor. I want to be able to pass this data along to the callback before calling execute, but since everything is abstract from the perspective of the monitor this is difficult. I'm looking for suggestions on how to do this in the best OO way possible, as of yet I haven't come up with anything I'm too fond of. Since the callbacks are sent to another class to actually be dispatched the data needs to end up inside them at some point.
For reference, the monitor abstract class
#pragma once
#include "DIVE_GUI_Types.h"
#include "DIVE_GUI_Callback.h"
#include "DIVE_GUI_Event_Dispatcher.h"
#include <map>
#include <string>
/*
Class to monitor events to be handled by the event system.
*/
class DIVE_GUI_Event_Monitor
{
private:
friend class DIVE_GUI_Kernel;
DIVE_GUI_Event_Dispatcher* m_Dispatcher;
static DIVE_HANDLE m_Active_GUI;
protected:
const std::string m_Event_ID;
std::map<DIVE_HANDLE, DIVE_GUI_Callback*> m_GUI_Map;
virtual bool Dispatch() = 0;
public:
void Update();
std::string Get_Event_ID() const { return m_Event_ID; }
DIVE_GUI_Event_Monitor(const std::string& id) : m_Event_ID(id) { }
void Add_Callback(DIVE_HANDLE, DIVE_GUI_Callback* function);
};
And the callback abstract class
#pragma once
/*
Abstract class representing a wrapper for a callback function as per the Command design pattern.
*/
class DIVE_GUI_Callback
{
public:
virtual void Excecute_Callback() const = 0;
};
Any and all opinions / suggestions are appreciated. Thanks!
If I correctly understood you, this data should be supplied to callback constructor. Suppose you have Callback1 and Callback2 derived from DIVE_GUI_Callback. So the code could look like:
DIVE_GUI_Event_Monitor* monitor;
monitor->Add_Callback(Callback1(specific_data_1));
monitor->Add_Callback(Callback2(specific_data_2));
This specific data then will be used in Excecute_Callback().
I'm implementing a mechanism similar to the observer design pattern for a multithreaded Tetris game. There is a Game class which contains a collection of EventHandler objects. If a class wants to register itself as a listener to a Game object it must inherit the Game::EventHandler class. On state change events a corresponing method is called on the EventHandler interface of each listener. This is what the code looks like:
class Game
{
public:
class EventHandler
{
public:
EventHandler();
virtual ~EventHandler();
virtual void onGameStateChanged(Game * inGame) = 0;
virtual void onLinesCleared(Game * inGame, int inLineCount) = 0;
private:
EventHandler(const EventHandler&);
EventHandler& operator=(const EventHandler&);
};
static void RegisterEventHandler(ThreadSafe<Game> inGame, EventHandler * inEventHandler);
static void UnregisterEventHandler(ThreadSafe<Game> inGame, EventHandler * inEventHandler);
typedef std::set<EventHandler*> EventHandlers;
EventHandlers mEventHandlers;
private:
typedef std::set<Game*> Instances;
static Instances sInstances;
};
void Game::RegisterEventHandler(ThreadSafe<Game> inGame, EventHandler * inEventHandler)
{
ScopedReaderAndWriter<Game> rwgame(inGame);
Game * game(rwgame.get());
if (sInstances.find(game) == sInstances.end())
{
LogWarning("Game::RegisterEventHandler: This game object does not exist!");
return;
}
game->mEventHandlers.insert(inEventHandler);
}
void Game::UnregisterEventHandler(ThreadSafe<Game> inGame, EventHandler * inEventHandler)
{
ScopedReaderAndWriter<Game> rwgame(inGame);
Game * game(rwgame.get());
if (sInstances.find(game) == sInstances.end())
{
LogWarning("Game::UnregisterEventHandler: The game object no longer exists!");
return;
}
game->mEventHandlers.erase(inEventHandler);
}
There are two problems that I often experience with this kind of pattern:
A listener object wants to unregister itself on an already deleted object resulting in a crash.
A event is fired to a listener that no longer exists. This happens most often in multithreaded code. Here's a typical scenario:
The game state changes in a worker thread. We want the notification to occur in the main thread.
The event is wrapped in a boost::function and sent as a PostMessage to the main thread.
A short time later this function object is processed by the main thread while the Game object is already deleted. The result is a crash.
My current workaround is the one that you can see in above code sample. I made the UnregisterEventHandler a static method which checks against a list of instances. This does help, but I find it a somewhat hackish solution.
Does anyone know of a set of guidelines on how to cleanly and safely implement notifier/listener system? Any advice on how to avoid the above pitfalls?
PS: If you need more information in order to answer this question you can find the relevant code online here: Game.h, Game.cpp, SimpleGame.h, SimpleGame.cpp, MainWindow.cpp.
The rule of thumb is that delete and new for an object should be near each other. E.g. in constructor and destructor or before and after a call where you use the object. So it's a bad practice to delete an object in another object when the latter one didn't create the former one.
I don't understand how you pack the events. It seems that you have to check whether the game is still alive before processing an event. Or you can use shared_ptr in events and other places to be sure that games are deleted last.
I write a lot of C++ code and needed to create an Observer for some game components I was working on. I needed something to distribute "start of frame", "user input", etc., as events in the game to interested parties. I had the same problem to consider...the firing of an event would lead to the destruction of another observer which may also subsequently fire. I need to handle this. I did not need to handle thread safety, but the design requirement I usually shoot for is to build something simple enough (API wise) that I can put in a few mutexes in the right place and the rest should take care of itself.
I also wanted it to be straight C++, not dependent on the platform or a specific technology (such as boost, Qt, etc.) because I often build and re-use components (and the ideas behind them) across different projects.
Here is the rough sketch of what I came up with as a solution:
The Observer is a singleton with keys (enumerated values, not strings) for Subjects to register interest in. Because it is a singleton, it always exists.
Each subject is derived from a common base class. The base class has an abstract virtual function Notify(...) which must be implemented in derived classes, and a destructor that removes it from the Observer (which it can always reach) when it is deleted.
Inside the Observer itself, if Detach(...) is called while a Notify(...) is in progress, any detached Subjects end up on a list.
When Notify(...) is called on the Observer, it creates a temporary copy of the Subject list. As it iterates over it, it compare it to the recently detached. If the target is not on it, Notify(...) is called on the target. Otherwise, it is skipped.
Notify(...) in the Observer also keeps track of the depth to handle cascading calls (A notifies B, C, D, and the D.Notify(...) triggers a Notify(...) call to E, etc.)
This is what the interface ended up looking like:
/*
The Notifier is a singleton implementation of the Subject/Observer design
pattern. Any class/instance which wishes to participate as an observer
of an event can derive from the Notified base class and register itself
with the Notiifer for enumerated events.
Notifier derived classes MUST implement the notify function, which has
a prototype of:
void Notify(const NOTIFIED_EVENT_TYPE_T& event)
This is a data object passed from the Notifier class. The structure
passed has a void* in it. There is no illusion of type safety here
and it is the responsibility of the user to ensure it is cast properly.
In most cases, it will be "NULL".
Classes derived from Notified do not need to deregister (though it may
be a good idea to do so) as the base class destrctor will attempt to
remove itself from the Notifier system automatically.
The event type is an enumeration and not a string as it is in many
"generic" notification systems. In practical use, this is for a closed
application where the messages will be known at compile time. This allows
us to increase the speed of the delivery by NOT having a
dictionary keyed lookup mechanism. Some loss of generality is implied
by this.
This class/system is NOT thread safe, but could be made so with some
mutex wrappers. It is safe to call Attach/Detach as a consequence
of calling Notify(...).
*/
class Notified;
class Notifier : public SingletonDynamic<Notifier>
{
public:
typedef enum
{
NE_MIN = 0,
NE_DEBUG_BUTTON_PRESSED = NE_MIN,
NE_DEBUG_LINE_DRAW_ADD_LINE_PIXELS,
NE_DEBUG_TOGGLE_VISIBILITY,
NE_DEBUG_MESSAGE,
NE_RESET_DRAW_CYCLE,
NE_VIEWPORT_CHANGED,
NE_MAX,
} NOTIFIED_EVENT_TYPE_T;
private:
typedef vector<NOTIFIED_EVENT_TYPE_T> NOTIFIED_EVENT_TYPE_VECTOR_T;
typedef map<Notified*,NOTIFIED_EVENT_TYPE_VECTOR_T> NOTIFIED_MAP_T;
typedef map<Notified*,NOTIFIED_EVENT_TYPE_VECTOR_T>::iterator NOTIFIED_MAP_ITER_T;
typedef vector<Notified*> NOTIFIED_VECTOR_T;
typedef vector<NOTIFIED_VECTOR_T> NOTIFIED_VECTOR_VECTOR_T;
NOTIFIED_MAP_T _notifiedMap;
NOTIFIED_VECTOR_VECTOR_T _notifiedVector;
NOTIFIED_MAP_ITER_T _mapIter;
// This vector keeps a temporary list of observers that have completely
// detached since the current "Notify(...)" operation began. This is
// to handle the problem where a Notified instance has called Detach(...)
// because of a Notify(...) call. The removed instance could be a dead
// pointer, so don't try to talk to it.
vector<Notified*> _detached;
int32 _notifyDepth;
void RemoveEvent(NOTIFIED_EVENT_TYPE_VECTOR_T& orgEventTypes, NOTIFIED_EVENT_TYPE_T eventType);
void RemoveNotified(NOTIFIED_VECTOR_T& orgNotified, Notified* observer);
public:
virtual void Reset();
virtual bool Init() { Reset(); return true; }
virtual void Shutdown() { Reset(); }
void Attach(Notified* observer, NOTIFIED_EVENT_TYPE_T eventType);
// Detach for a specific event
void Detach(Notified* observer, NOTIFIED_EVENT_TYPE_T eventType);
// Detach for ALL events
void Detach(Notified* observer);
/* The design of this interface is very specific. I could
* create a class to hold all the event data and then the
* method would just have take that object. But then I would
* have to search for every place in the code that created an
* object to be used and make sure it updated the passed in
* object when a member is added to it. This way, a break
* occurs at compile time that must be addressed.
*/
void Notify(NOTIFIED_EVENT_TYPE_T, const void* eventData = NULL);
/* Used for CPPUnit. Could create a Mock...maybe...but this seems
* like it will get the job done with minimal fuss. For now.
*/
// Return all events that this object is registered for.
vector<NOTIFIED_EVENT_TYPE_T> GetEvents(Notified* observer);
// Return all objects registered for this event.
vector<Notified*> GetNotified(NOTIFIED_EVENT_TYPE_T event);
};
/* This is the base class for anything that can receive notifications.
*/
class Notified
{
public:
virtual void Notify(Notifier::NOTIFIED_EVENT_TYPE_T eventType, const void* eventData) = 0;
virtual ~Notified();
};
typedef Notifier::NOTIFIED_EVENT_TYPE_T NOTIFIED_EVENT_TYPE_T;
NOTE: The Notified class has a single function, Notify(...) here. Because the void* is not type safe, I created other versions where notify looks like:
virtual void Notify(Notifier::NOTIFIED_EVENT_TYPE_T eventType, int value);
virtual void Notify(Notifier::NOTIFIED_EVENT_TYPE_T eventType, const string& str);
Corresponding Notify(...) methods were added to the Notifier itself. All these used a single function to get the "target list" then called the appropriate function on the targets. This works well and keeps the receiver from having to do ugly casts.
This seems to work well. The solution is posted on the web here along with the source code. This is a relatively new design, so any feedback is greatly appreciated.