What are the principles of an event system in C++? - c++

First of all, I know there are excellent implementations (Qt, Boost, cpp-event, etc.), but I ask the question because I want to know how it works !
If I understand correctly, the "event system" uses the Observer pattern : some objects are observing, waiting for something to happen... and some others send signals. All right.
So, let's say I've got my observer class, with this kind of thing :
void Observer::getNotified()
{
// Do stuff
}
My question is : how to manage dynamically what kind of stuff should be done ? I've seen a lot of people saying specifically not to use functions pointers. For my current need, I can do a switch statement, a enum type, and select different behaviors, but that's not very satisfying. So, if it's not functions pointers, how is it done ?

There is a lot of different implementations possible (whatever the language), but the abstract idea is :
have an event type identifier to know wich events have been fired by the observed object (it can be whatever works);
have a list of observers (or several, one by event type?) registered in the registered objects - that suppose that the observers are functors (function pointer or object that act like a function) or are objects with a known interface (with a virtual method to call ion event fired);
when an event is fired (by calling a function on the observed object) we just go through the list of observers registered for the event's type and pass the event information (id plus maybe data ) to the observer to be processed;
Here is a simplist implementation :
enum EventType
{
Event_A,
Event_B,
};
class Observer // for this example i'll suppose observer inherits this class
{
virtual void catchEvent( EventType e ) = 0; // for sake of the example I just need the event type, not the data, but it's often required
virtual ~Observer(){}; // virtual base classes require this to work fine.
};
class Observed
{
typedef std::vector<Observer*> ObserverList;
typedef std::map< EventType, ObserverList > ObserversTable;
ObserversTable m_observers; // we have observers for each event type
public:
void addObserver( Observer& observer, EventType eType )
{ m_observers[ eType ].push_back( observer ); } // this is simplist, to say the least...
void sendEvent( EventType event ) // here we send the event, it will be catched by observers
{ // note : often this type of system is "buffered", but here we will process it immediatly as it's a simple example
ObserverList& observers = m_observers[ event ];
for ( ObserverList::iterator it = observers.begin(); it != observers.end(); ++it )
{
Observer* observer = *it;
observer->catchEvent( event ); // here an observer receive the event
}
}
};
It's really a basic example but that might help you understand the idea.

See this rather excellent article from Pete Goodliffe, which routes to different methods depending on the event type being notified.
If you need to choose actions within a single event type, then typically your code would choose depending on the data passed in the notification.

Related

Pass argument to function taking parent class argument without casting argument to parent class

I am building a Boost state machine. My state has a pointer to its own backend (fsm) to process events. All events of my state machine are children of an MySatetMachineEvent class (with an example child like EventChild). State transitions are only defined for children like EventChild of MySTateMachineEvent.
To clean up my code I want to create a function processEvent(MySatetMachineEvent event) taking all possible events. This class should then call the process_event() function with the passed event.
For example:
processEvent(MyStateMachineEvent event)
{
fsm.process_event(event);
}
processEvent(EventCild());
should case a call of
fsm.process_event(EventChild());
Creating such a function causes the error that fsm.process_event() is called with an instance of MyStateMachineEvent. As written above there are no state transitions defined for this case.
This hinders my state machine from working in a proper manner, obviously.
So my question is if there is a way to pass any EventChild or other child of MyStateMachineEvent to my processEvent(MySTateMachineEvent event) function without casting the passed Object to MyStateMachineEvent.
I am aware of the solution to overlode my function like
processEvent(EventChild event) {
fsm.process_event(event);
}
This would cause may functions (with the exact same line of code inside) in my case, thus i am looking for a cleaner and more fancy solution.
You can use a function template:
template <typename Event>
void processEvent(Event event)
{
fsm.process_event(event);
}
Every instantiation will preserve the exact type of the event argument that was passed in.
Albeit I like Vittorio Romeo's template approach, it might not be suitable if you e. g. have some kind of event queue holding arbitrary events. A polymorphic approach could be more suitable then:
class MyStateMachineEvent
{
public:
virtual ~MyStateMachineEvent() { }
virtual void doOrGetSomething() = 0;
};
class EventChild : public MyStateMachineEvent
{
public:
void doOrGetSomething() override;
};
Now your processEvent function might accept a reference, just as would the fsm's variant as well:
void processEvent(MyStateMachineEvent& event)
{
fsm.processEvent(event);
}
void FSM::processEvent(MyStateMachineEvent& event)
{
// ...
event.doOrGetSomething();
// ...
}
And usage might look like this:
std::queue<std::unique_ptr<MyStateMachineEvent>> events;
events.emplace(new EventChild());
processEvent(**events.front());
events.pop();

How can I reduce coupling in my Event Bus implementation

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"

Delegates with multiple notifications in C++

I've been considering the best way to implement delegates in C++, and so far I'm inclined to using std::function callbacks. However, some of my classes issue several delegate notifications (such as opened, closed, and changed_state). Instances interested in getting delegate notifications should assign one of its own methods (the fact that it can be private is a plus) to the event it's interested in listening to. It would be expected, however, that when some instance subscribes to any of the delegates, it would subscribe to all of them. This means that it wouldn't happen that event Foo is being issued to one instance, while event Bar is being issued to a different one. Is there a way I could enforce this condition? At no point should the callbacks be assigned to different instances (assume atomicity).
I know I could consider having a single callback with calling codes or something, but in this case that's not an option (for several reasons, one of them being that it would imply an unreasonable amount of refactoring at this point).
Note: I know that are other discussions on the topic of C++ delegates, but these usually consider a single event type, not several.
An example of what I'm considering:
class Connector
{
public:
typedef struct
{
std::function<void()> opened;
std::function<void()> closed;
std::function<void()> changed_state;
} Delegate;
Delegate delegate;
};
// Somewhere else
Connector c;
Listener l;
// This should not be manual. Ideally: c.delegate = l;
c.delegate.opened = l.handle_opened;
c.delegate.closed = l.handle_closed;
c.delegate.changed_state = l.handle_changed_state;
Add operator= for that:
class Connector
{
public:
struct Delegate
{
Delegate& operator = (const Listener& l)
{
opened = l.handle_opened;
closed = l.handle_closed;
changed_state = l.handle_changed_state;
return *this;
}
std::function<void()> opened;
std::function<void()> closed;
std::function<void()> changed_state;
};
Delegate delegate;
};
and then you can have your syntax:
c.delegate = l;

How to implement the observer pattern safely?

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.

Prevent Firing Signals in Qt

We have a QCheckBox object, when user checks it or removes check we want to call a function so we connect our function to stateChanged ( int state ) signal. On the other hand, according to some condition we also change the state of QCheckBox object inside code, and this causes the unwanted signal.
Is there any way to prevent firing signal under some conditions?
You can use the clicked signal because it is only emitted when the user actually clicked the check box, not when you manually check it using setChecked.
If you just don't want the signal to be emitted at one specific time, you can use QObject::blockSignals like this:
bool oldState = checkBox->blockSignals(true);
checkBox->setChecked(true);
checkBox->blockSignals(oldState);
The downside of this approach is that all signals will be blocked. But I guess that doesn't really matter in case of a QCheckBox.
You can always block signal emission on QObjects using QObject::blockSignals(). Note that to be correct about things, you should remember the old state (returned from the function call), and restore it when you are done.
At my job, we prefer RAII for this sort of thing. A simple class to do so might look like this:
class SignalBlocker
{
public:
SignalBlocker( QObject *obj ) : m_obj( obj ), m_old( obj->blockSignals( true ) )
{
}
~SignalBlocker()
{
m_obj->blockSignals( m_old );
}
private:
QObject *m_obj;
bool m_old;
};
Edit: Starting with Qt 5.3, see QSignalBlocker (h/t to HappyCactus in comments)
While learning Qt, I ran into this problem with a set of interconnected widgets that I wanted to update "atomically". I liked #cjhuitt's solution, but found that it goes even better with a bit of syntactic sugar based on proxy objects. Here's the approach that I used...
First, I defined a class template for a blocker proxy object. Like Caleb's, this blocks the signals on construction, and then restores their previous state on destruction. However, it also overloads the -> operator to return a pointer to the blocked object:
template<class T> class Blocker {
T *blocked;
bool previous;
public:
Blocker(T *blocked)
: blocked(blocked),
previous(blocked->blockSignals(true)) {}
~Blocker() { blocked->blockSignals(previous); }
T *operator->() { return blocked; }
};
Next, I defined a small template function to construct and return a Blocker:
template<class T> inline Blocker<T> whileBlocking(T *blocked) {
return Blocker<T>(blocked);
}
Putting this all together, I'd use it like this:
whileBlocking(checkBox)->setChecked(true);
or
whileBlocking(xyzzySpin)->setValue(50);
This gets me all the benefits of RAII, with automatically paired blocking and restore around the method call, but I don't need to name any wrapper or state flags. It's nice, easy, and pretty darn foolproof.
You can QObject::disconnect to remove the corresponding signal-slot connection and can QObject::connect again once you are done...
In QObject derived classes, you can call blockSignals(bool) to prevent the object from emitting signals. So for example:
void customChangeState(bool checked)
{
blockSignals(true);
ui->checkBox->setCheckState(Qt::Checked);
// other work
blockSignals(false);
}
The above method would change the check state without clicked, stateChanged, or any other signals being emitted.
Qt5.3 introduced the QSignalBlocker class that does exactly what needed in an exception safe way.
if (something) {
const QSignalBlocker blocker(someQObject);
// no signals here
}
Even in QT5, its a bit cumbersome when there are many/several things to block. Here's a multi-object version that is concise to use:
class SignalBlocker
{
public:
SignalBlocker(QObject *obj)
{
insert( QList<QObject*>()<<obj );
}
SignalBlocker(QList<QObject*> objects)
{
insert(objects);
}
void insert(QList<QObject*> objects)
{
for (auto obj : objects)
m_objs.insert(obj, obj->signalsBlocked());
blockAll();
}
void blockAll() {
for( auto m_obj : m_objs.keys() )
m_obj->blockSignals(true);
}
~SignalBlocker()
{
for( auto m_obj : m_objs.keys() )
m_obj->blockSignals( m_objs[m_obj] );
}
private:
QMap<QObject*,bool> m_objs;
};
usage:
void SomeType::myFunction()
{
SignalBlocker tmp( QList<QObject*>()
<< m_paramWidget->radioButton_View0
<< m_paramWidget->radioButton_View1
<< m_paramWidget->radioButton_View2
);
// Do more work, ...
}
When some UI element should not respond to user it is appropriate to disable it. So that user would know that this element is not accepting input.