Generic observer pattern in C++ - c++

In many cases in my application i need class A to register itself as a listener on class B to receive notification when something happens. In every case i define a separate interface B implements and A can call do. So for example, A will have the following method:
void registerSomeEventListener(SomeEventListener l);
Also, in many cases, B will need to support multiple listeners so i reimplement the registration and notifyAll logic.
One generic way i know is to have some EventListener (implement by A) and EventNotifier (implement by B) classes. In this case each event is identified by a string and A implements the method:
void eventNotified(string eventType);
I think this is not a good solution. It will result in many if-else statements in case A listens to several events and might result in bugs when event names are changed only in the listener or the notifier.
I wonder what is the correct way to implement the observer pattern in C++?

Take a look at boost::signals2. It provides a generic mechanism to define "signals" where other objects can register. The signal owner can then notify observers by "firing" the signal. Instead of register-methods, the subject defines signals as members which then keep track of connected observers and notify them when initiated. The signals are statically typed and accept every function with the matching signature. This has the advantage that there is no need for inheritance and thus a weaker coupling than the traditional observer inheritance hierarchy.
class Subject {
public:
void setData(int x) {
data_ = x;
dataChanged(x);
}
boost::signals2<void (int)> dataChanged;
private:
int data_;
};
class Observer {
public:
Observer(Subject& s) {
c_ = s.dataChanged.connect([&](int x) {this->processData(x);});
}
~Observer() {
c_.disconnect();
}
private:
void processData(int x) {
std::cout << "Updated: " << x << std::endl;
}
boost::signals2::connection c_;
};
int main() {
Subject s;
Observer o1(s);
Observer o2(s);
s.setData(42);
return 0;
}
In this example, the subject holds some int data and notifies all registered observers when the data is changed.

Lets say you have a generic event fireing object:
class base_invoke {
public:
virtual ~base_invoke () {};
virtual void Invoke() = 0;
}
But you want to fire events on different types of objects, so you derive from base:
template<class C>
class methodWrapper : public base_invoke {
public:
typedef void (C::*pfMethodWrapperArgs0)();
C * mInstance;
pfMethodWrapperArgs0 mMethod;
public:
methodWrapper(C * instance, pfMethodWrapperArgs0 meth)
: mInstance(instance)
{
mMethod = meth;
}
virtual void Invoke () {
(mInstance->*mMethod)();
}
}
Now if you create a wrapper for a collection of pointers to base_invoke you can call each fireing object and signal whichever method on whichever class you'd like.
You can also turn this collection class into a factory for the fireing objects. to simplyfy the work.
class Event {
protected:
Collection<base_invoke *> mObservers;
public:
// class method observers
template<class C>
void Add (C * classInstance, typename methodWrapper<C>::pfMethodWrapperArgs0 meth) {
methodWrapper<C> * mw = NEW(methodWrapper<C>)(classInstance, meth);
mObservers.Add(ObserverEntry(key, mw));
}
void Invoke () {
int count = mObservers.Count();
for (int i = 0; i < count; ++i) {
mObservers[i]->Invoke();
}
}
};
And your done with the hard work. Add an Event object anyplace you want listeners to subscribe. You'll probably want to expand this to allow removal of listeners, and perhaps to take a few function parameters but the core is pretty much the same.

Related

What is an alternative to using templates on a virtual member function?

I am creating a simple event system where multiple listeners can be notified on a specific topic and when an event is fired, it can pass a generic payload to the event, and the listeners will match the format of the fired event. However, because it's not possible to use templates on a virtual function, how else can I achieve this?
class AEventListener
{
public:
template<class T>
struct PayloadObject {
T obj;
};
explicit AEventListener();
virtual ~AEventListener();
//error here because T is undefined. Each PayloadObject may have a different type
virtual void notify(vector<shared_ptr<PayloadObject<T>>> payload) = 0;
};
The notify method is called when an event topic has a listener subscribed, but I want a generic way of just passing a load of random objects to the listener.
For example
fireEvent("test.topic", Payload { 0, "hello", 123 });
//...
listener.notify(payload);
How would I go about this in C++?
I have managed to get around this, although I don't think this is the best way and could slow down performance.
template<class T>
struct PayloadObject : public APayloadObject {
T obj;
PayloadObject(T obj) {
this->obj = obj;
}
~PayloadObject() override {
};
};
struct APayloadObject {
virtual ~APayloadObject();
};
Firing:
vector<shared_ptr<APayloadObject>> payload;
payload.push_back(shared_ptr<PayloadObject<int>>(new PayloadObject<int>(5))); //payload[0] = int - 5
Events::fire(EventKeys::DISCONNECTION_EVENT, payload);
Notifying:
shared_ptr<PayloadObject<int>> number = dynamic_pointer_cast<PayloadObject<int>>(payload[0]);
int id = number.get()->obj; //payload[0] = int - 5
One simple approach is to come up with a common base or common interface for the Payload objects. So that they are not a template class.
struct Payload {
virtual ~Payload() = default;
virtual std::string foo() const;
virtual std::string bar() const;
};
Another way is to use a variant type for the payload objects:
using Message_t = boost::variant<A, B, C>;
and then make AEventListener take the Message_t type so that it doesn't require the member function to be a template.
class AEventListener
{
public:
virtual ~AEventListener();
virtual void notify(std::vector<Message_t> payload) = 0;
};
In C++17 you could use std::variant for this instead of boost.
Yet another way is to skip using a variant, and just make it so that the Listener must implement three different functions, one for each type:
class AEventListener
{
public:
virtual ~AEventListener();
virtual void notifyA(A payload) = 0;
virtual void notifyB(B payload) = 0;
virtual void notifyC(C payload) = 0;
};
More generally, it is pretty difficult in C++ to make a concept like "Function object that is callable with any particular type of arguments". This is in part because... it is not very useful, there is not much that you can do generically with data of ANY type that you can assume nothing about.
So I would suggest that you think hard about refining your Event Listener concept, and make more concrete what it is that objects of this type are ACTUALLY supposed to be required to do.

Low latency callback in C++

I have an event driven application. I want to keep the event handler (EventHandler class capable of many/all events) a common implementation - while allowing the EventSource be changeable (specifically - at compile time).
To couple the EventHandler with the EventSource, I will have to store an instance of handler within the EventSource. I tried to store handlers of various forms:
pointer to an interface of EventHandler (that has public handler methods defined in concrete EventHandler's
instance of std::function - this provided greatest flexibility
However, in both cases, the latency in calling the target method/lambda was quite high (on my test setup about 250ns) - and to worse, was inconsistent. May be due to virtual table and/or heap allocation and/or type erasure ???
In order to reduce this latency, I want to make use of templates.
The best I could come up with is:
template <typename EventHandler>
class EventSource1
{
EventHandler* mHandler;
public:
typedef EventHandler EventHandlerType;
void AssignHandler (EventHandler* handler)
{
this->mHandler = handler;
}
void EventuallyDoCallback (int arbArg)
{
this->mHandler->CallbackFunction (arbArg);
}
};
template <EventSourceType>
class EventSourceTraits
{
typedef EventSourceType::EventHandlerType EventHandlerType;
static void AssignHandler (EventSourceType& source, EventHandlerType* handler)
{
source.AssignHandler(handler);
}
};
class EventHandler
{
public:
void CallbackFunction (int arg)
{
std::cout << "My callback called\n";
}
};
int main ()
{
EventSource1<EventHandler> source; /// as one can notice, EventSource's need not to know the event handler objects.
EventHandler handler;
EventSourceTraits<EventSource1>::AssignHandler (source, &handler);
}
This method impose a restriction that all my EventSource's to be a template classes.
Question is: Is this best way to achieve consistent and low latency to callback? Can this code be improved to avoid the event source classes be completely independent of event handler objects' type ?
Is this best way to achieve consistent and low latency to callback?
As suggested in the comments to the question, I'd rather try and measure to know if that's really a problem and what's the best alternative for you.
There doesn't exist the best way, it mostly depends on the actual problem.
can this code be improved to avoid the event source classes be completely independent of event handler objects' type ?
Maybe the following can be a good point from which to start to achieve that:
#include <iostream>
class EventSource1
{
using invoke_t = void(*)(void *C, int value);
template<typename T, void(T::*M)(int)>
static void proto(void *C, int value) {
(static_cast<T*>(C)->*M)(value);
}
invoke_t invoke;
void *handler;
public:
template<typename T, void(T::*M)(int) = &T::CallbackFunction>
void AssignHandler (T* ref)
{
invoke = &proto<T, M>;
handler = ref;
}
void EventuallyDoCallback (int arg)
{
invoke(handler, arg);
}
};
class EventHandler
{
public:
void CallbackFunction (int arg)
{
std::cout << "My callback called: " << arg << std::endl;
}
};
int main ()
{
EventSource1 source;
EventHandler handler;
source.AssignHandler(&handler);
source.EventuallyDoCallback(42);
}
See it on wandbox.

"Interface Object" pattern. Reasonable?

Lately I've been using some pattern quite a lot but I don't know if it is really good or not.
It goes as follows:
I have a set of function, lets call them ActionFoo, ActionBar and ActionZapper. These might differ in implementation but generally are used for same things across these. They may or may not be used together in a sequence(i.e. some of them can be used as a standalone), but there are some cases when they are, indeed grouped.
If I DO want to use them in a sequence I generally have two options:
1) write them manually each time
2) create a class hierarchy:
Approach #1:
void SomeActionSequence1()
{
ActionFoo1(1);
ActionBar1("Moo");
ActionZapper1("Moo", 42);
}
void SomeActionSequence2()
{
ActionFoo4(1);
ActionBar2("Moo");
ActionZapper1("Moo", 42);
}
This has drawbacks:
1) I won't have an ability to store state and will have to pass a lot of parameters to these Actions
2) I won't really have a coherent interface and won't be able to easily use autocompletion
Approach #2
class Base
{
public:
Base(){}
virtual ~Base(){}
virtual void ActionFoo(int) = 0;
virtual void ActionBar(string) = 0;
virtual void ActionZapper(string, int) = 0;
void ExecuteActionSequence();
};
void Base::ExecuteActionSequence()
{
ActionFoo(1);
ActionBar("Moo");
ActionZapper("Moo", 42);
}
Derived1 : public Base
{
void ActionFoo(int){/*some inplementation*/};
void ActionBar(string){/*some inplementation*/};
void ActionZapper(string, int){/*some inplementation*/};
}
Derived2 : public Base
{
void ActionFoo(int){/*some inplementation*/};
void ActionBar(string){/*some inplementation*/};
void ActionZapper(string, int){/*some inplementation*/};
}
and use it kinda like this:
Base* actionSequence = new Derived1();
actionSequence->ExecuteActionSequence();
Correct virtuals will be used and all seems ok except 2 small things:
1) Extensibility - I will have to write a class for each complex action
2) More importantly - either a lot of functions will be duplicated between these classes or
I will have a hierarchical tree too complex on my hands
I kinda "circumvent" problems of both approaches with "Interface Object" pattern (note, the name is mine, maybe it has a proper one)
What I do is this:
class InterfaceClass
{
public:
InterfaceClass(){};
~InterfaceClass(){};
void ActionFoo(int i)
{
if(fooPlaceholder != 0)
fooPlaceholder(i);
}
void ActionBar(string str)
{
if(barPlaceholder != 0)
barPlaceholder(str);
}
void ActionZapper(string str, int i)
{
if(zapperPlaceholder != 0)
zapperPlaceholder(str, i);
};
void ExecuteActionSequence();
std::function<void(int)> fooPlaceholder;
std::function<void(string)> barPlaceholder;
std::function<void(string, int)> zapperPlaceholder;
};
void InterfaceClass::ExecuteActionSequence()
{
ActionFoo(1);
ActionBar("Moo");
ActionZapper("Moo", 42);
}
in my application I do:
InterfaceClass complexAction;
complexAction.fooPlaceholder = ActionFoo;
complexAction.barPlaceholder = ActionBar;
complexAction.zapperPlaceholder = ActionZapper;
complexAction.ExecuteActionSequence();
Note that ActionFoo, ActionBar and ActionZapper are free functions, but at the same time I am using them in an interface. Also - I can easily switch between implementations of these functions, even at runtime(If I need this).
The advantage of this approach is - there is no need to create separate class structures for new actions and there is no code duplication of Action* functions.
Also - all functions can be brought to scope only where the complexAction is initialized.
The disadvantages are, I think, that it is not obvious just which Action* function is being used in the InterfaceClass object. Also - there is no ability to dynamic_cast such a class to determine just what it is.
I highly suspect that these are not only disadvantages of such approach so I would like comments about that.
It sounds like you want the Chain of Responsibility pattern
abstract class Action {
Action child;
Action(Action child) { this.child = child; }
Action() { }
void doAction(StateContext context);
void execute(StateContext context) {
if (child) child.execute(context);
doAction(context);
}
}
class ZapAction extends Action {
ZapAction(String theString, int theValue, Action child) { ... }
void doAction(Context context) { context.setZap(theString); }
}
Action actionSequenceAlpha = new ZapAction("", 1, new FooAction());
Action actionSequenceBeta = new FooAction(new BarAction(new ZapAction));
Advantages - Don't need to change this base object with a fixed set of strategies when you add a new Action, you can map actions in all sorts of fun and exciting ways, each object has a single responsibility and it is a nice standard pattern so everyone knows what is going on.
The other option would be to separate the sequence from the Action. Have an Action interface with the three Actions inheriting it. Then have a Sequence class with an execute method and a List of Actions
class Action { }
class FooAction extends Action { }
class Sequence {
List<Action> actions;
void execute() {
foreach (action : actions) action.execute();
}
}

How to avoid downcast?

I have an implementation of a State Pattern where each state handles events it gets from a event queue. Base State class therefore has a pure virtual method void handleEvent(const Event*). Events inherit base Event class but each event contains its data that can be of a different type (e.g. int, string...or whatever). handleEvent has to determine the runtime type of the received event and then perform downcast in order to extract event data. Events are dynamically created and stored in a queue (so upcasting takes place here...).
I know that downcasting is a sign of a bad design but is it possible to avoid it in this case? I am thinking of Visitor Pattern where base class State would contain virtual handlers for each event but then again downcast will need to take place in the piece of code which dequeues event from a queue and passes it to the current state. (At least in this case big switch(eventID) would be only at one place...). Is Visitor Pattern the best way (best practice) to avoid downcasting?
Here is the pseudo-code (I am passing boost::shared_ptr in this example but downcasting happens anyway):
enum EventID
{
EVENT_1,
EVENT_2,
...
};
class Event
{
EventID id;
public:
Event(EventID id):id(id){}
EventID id() const {return id;}
virtual ~Event() = 0;
};
class Event1 : public Event
{
int n;
public:
Event1(int n):Event(EVENT_1), n(n){}
int getN() const {return n;}
};
class Event2 : public Event
{
std::string s;
public:
Event2(std::string s):Event(EVENT_2), s(s){}
std::string getS() const {return s;}
};
typedef boost::shared_ptr<Event> EventPtr;
class State
{
...
public:
...
virtual ~State() = 0;
virtual void handleEvent(const EventPtr& pEvent) = 0;
};
class StateA : public State
{
...
public:
void handleEvent(const EventPtr& pEvent)
{
switch(pEvent->id())
{
case EVENT_1:
int n = boost::static_pointer_cast<Event1>(pEvent)->getN();
...
break;
case EVENT_2:
std::string s = boost::static_pointer_cast<Event2>(pEvent)->getS();
...
break;
...
}
}
}
The typical visitor pattern performs no downcast, thanks to a double-dispatch strategy:
// Visitor.hpp
class EventBar;
class EventFoo;
class Visitor {
public:
virtual void handle(EventBar const&) = 0;
virtual void handle(EventFoo const&) = 0;
};
// Event.hpp
class Visitor;
class Event {
public:
virtual void accept(Visitor&) const = 0;
};
And the implementations:
// EventBar.hpp
#include <Event.hpp>
class EventBar: public Event {
public:
virtual void accept(Visitor& v);
};
// EventBar.cpp
#include <EventBar.hpp>
#include <Visitor.hpp>
void EventBar::accept(Visitor& v) {
v.handle(*this);
}
The key point here is that in v.handle(*this) the static type of *this is EventBar const&, which selects the correct virtual void handle(EventBar const&) = 0 overload in Visitor.
The idea of events is to pass detailed objects through generalized (and agnostic) interface.
Downcast is inevitable and part of the design. Bad or good, it's disputable.
Visitor pattern only hides the casting away from you. It's still performed behind the scenes, types resolved via virtual method address.
Because your Event already has the id, it's not completely agnostic of the type, so casting is perfectly safe. Here you're watching the type personally, in visitor pattern you're making compiler take care of that.
"Whatever goes up must go down".

How pass data to 'generic' observer? As arguments or as a single struct?

I am busy adding a generic observer mechanism to a legacy C++ application (using Visual Studio 2010, but not using .Net, so .Net delegates are out of the question).
In the design I want to separate the application-specific part as much as possible from the generic observer mechanism.
The most logical way of implementing observers seems this way:
class IDoThisObserver
{
public:
void handlDoThis(int arg1, int arg2) = 0;
};
For every type of observer (IDoThisObserver, IDoThatObserver, ...) the arguments of the methods (handleDoThis, handleDoThat) are different.
What remains in a generic way of storing the observers, like this:
template<typename T>
class ObserverContainer
{
public:
void addObserver (T &t) {m_observers.push_back(&t);}
private:
std::list<T*> m_observers;
};
Calling an observer can't be generalized since the arguments are different for every observer type.
An alternative way would be to 'pack' all arguments into one argument, like this:
struct DoThisInfo
{
DoThisInfo (int arg1, int arg2) : m_arg1(arg1), m_arg2(arg2) {}
int m_arg1;
int m_arg2;
};
And then define a more generic observer, like this:
template<typename T>
class IObserver
{
public:
void notify(const T &t) = 0;
};
And a collection of these observers would then become this:
template<typename T>
class ObserverContainer
{
public:
void addObserver (IObserver<T> &obs) {m_observers.push_back(&obs);}
private:
std::list<IObserver<T>*> m_observers;
};
Now, much more logic can be centrally added to this ObserverContainer, including calling all observers. The 'initiator' of the call only needs to create and fill in the notification structure.
Classes that want to inherit from multiple kinds of observers, need to do it like this:
class MyObserver : public IObserver<NotifyThis>, public IObserver<NotifyThat>
{
...
};
Which of these approaches (observers with multiple explicit arguments or with one struct argument) seems the best? Are there any advantages or disadvantages to either of these approaches?
EDIT: I looked a bit further to alternative approaches, and the Slot/Signal approach seems another good candidate. Are there any important disadvantages in Slot/Signal that I should know of?
Why not just do:
class IObserver {
// whatever is in common
};
class IDoThisObserver : public IObserver
{
public:
void handlDoThis(int arg1, int arg2) = 0;
};
class IDoThatObserver : public IObserver
{
public:
void handlDoThat(double arg1) = 0;
};
?
Then you have:
class ObserverContainer
{
public:
void addObserver (IObserver* t) {m_observers.push_back(t);}
private:
std::list<IObserver*> m_observers;
};
The design with the struct argument is definitely better as it allows for generic code to be written in the ObserverContainer. It's generally a good design practice to replace longish argument lists with objects that encapsulate the arguments and this is a good example of the payoff. By creating a more general abstraction for your notify method (with the struct you're defining notify as a method that takes a chunk of "data" whereas with the arg list you're defining a method that takes two numbers) you allow yourself to write generic code that uses the method and doesn't have to concern itself with the exact composition of the passed in chunk of data.
Have you looked into Boost.Signals? Better than to reimplement the wheel.
As for Parameters: Calling an observer/slot should conceptionally be the same as if you would call an ordinary function. Most SignalSlots-Implementations allow multiple Parameters, so use it. And please use different signals for different observer types, then there is no need to pass around data in Variants.
Two Disadvantages of the Observer-Pattern/SignalSlots i have seen:
1) Program flow is difficult or even impossible to understand by looking only at the source.
2) Heavily dynamic programs with lots of Observers/SignalSlots may encounter a "delete this"
Everything aside, i like Observers/SignalSlots more than subclassing and thus high coupling.
I don't think either of your approaches would fit your requirement as is. However a little modification using a DataCarrier containing the dataset passed across all the observers wherein each observer would know what to read would do the trick. The sample code below might clear it (note i have not compiled)
enum Type {
NOTIFY_THIS,
NOTIFY_THAT
};
struct Data {
virtual Type getType() = 0;
};
struct NotifyThisData: public Data {
NotifyThisData(int _a, int _b):a(_a), b(_b) { }
int a,b;
Type getType() { return NOTIFY_THIS; }
};
struct NotifyThatData: public Data {
NotifyThatData(std::string _str):str(_str) { }
std::string str;
Type getType() { return NOTIFY_THAT; }
};
struct DataCarrier {
std::vector<Data*> m_TypeData;
};
class IObserver {
public:
virtual void handle(DataCarrier& data) = 0;
};
class NotifyThis: public virtual IObserver {
public:
virtual void handle(DataCarrier& data) {
vector<Data*>::iterator iter = find_if(data.m_TypeData.begin(), data.m_TypeData.end(), bind2nd(functor(), NOTIFY_THIS);
if (iter == data.m_TypeData.end())
return;
NotifyThisData* d = dynamic_cast<NotifyThisData*>(*iter);
std::cout << "NotifyThis a: " << d->a << " b: " << d->b << "\n";
}
};
class NotifyThat: public virtual IObserver {
public:
virtual void handle(DataCarrier& data) {
vector<Data*>::iterator iter = find_if(data.m_TypeData.begin(), data.m_TypeData.end(), bind2nd(functor(),NOTIFY_THAT);
if (iter == data.m_TypeData.end())
return;
NotifyThatData* d = dynamic_cast<NotifyThatData*>(*iter);
std::cout << "NotifyThat str: " << d->str << "\n";
}
};
class ObserverContainer
{
public:
void addObserver (IObserver* obs) {m_observers.push_back(obs);}
void notify(DataCarrier& d) {
for (unsigned i=0; i < m_observers.size(); ++i) {
m_observers[i]->handle(d);
}
}
private:
std::vector<IObserver*> m_observers;
};
class MyObserver: public NotifyThis, public NotifyThat {
public:
virtual void handle(DataCarrier& data) { std::cout << "In MyObserver Handle data\n"; }
};
int main() {
ObserverContainer container;
container.addObserver(new NotifyThis());
container.addObserver(new NotifyThat());
container.addObserver(new MyObserver());
DataCarrier d;
d.m_TypeData.push_back(new NotifyThisData(10, 20));
d.m_TypeData.push_back(new NotifyThatData("test"));
container.notify(d);
return 0;
}
This way u need to modify only the enum if u add a new structure.
Also u can use boost::shared_ptr to handle the mess of pointers.
I wouldn't get the syntax right so I'm just going to list the declarations to illustrate the structures. A generic Observer could be made to expect a parameter that is either subclassed to specific forms of your required parameters or is struct including a horizontal mapping of all primitive parameters that will be required by your Observers. Then the ObserverContainer could function as an AbstractFactory and each subclass of the ObserverContainer could be DoThatObserverFactory and DoThisObserverFactory. The factory would build an observer and assign a configuration to the observer to tell it which parameter to expect.
class AbstractObserverFactory {...};
class DoThatObserverFactory : AbstractObserverFactory {...};
class DoThisObserverFactory : AbstractObserverFactory {...};
class ObserverParam {...};
class DoThatObserverParam : ObserverParam {...};
class DoThisObserverParam : ObserverParam {...};
class Observer;
class DoThisObserver : public Observer
{
public:
void handlDoThis(DoThisObserverParam);
};