c++ completely generic event dispatcher - c++

I try again to explain better again what I would achieve.
I would like make a thing like this (inspired to Unity's UnityEvent):
Public "variables" declared in some classes:
GameEvent<> OnEnemySpawn = GameEvent<>();
GameEvent<string> OnPlayerSpawn = GameEvent<string>();
GameEvent<string, float> OnEnemyDie = GameEvent<string, float>();
Referral where some other classes subscribe their methods:
...
enemySpawner.OnEnemySpawn.Subscribe(IncreaseEnemyAliveCountByOne);
...
playerSpawner.OnPlayerSpawn.Subscribe(NewPlayerSpawned);
...
enemy.OnEnemyDie.Subscribe(IncreasePlayerScore);
...
// Subscribed methods declaration
void IncreaseEnemyAliceCountByOne() { ... }
void NewPlayerSpawned(string playerName) { ... }
void IncreasePlayerScore(string playerName, float scoreToAdd) { ... }
And then GameEvent class would be able to notify the event happens:
...
OnEnemySpawn.Notify();
...
OnPlayerSpawn.Notify(newPlayer.PlayerName);
...
OnEnemyDie.Notify(playerKiller.PlayerName, scoreOnKill);
...
Actually, I achieved the declaration and subscription part creating this class:
templace<class ... T>
class GameEvent
{
private:
std::vector<std::function<void(T...)>> _subscribers;
public:
void Subscribe(std::function<void(T...)> newSubscriber)
{
_subscribers.push_back(newSubscriber);
}
}
The thing that makes me crazy is how implement the Notify method. How should I know how many parameters I received and which types they have
void Notify(T...)
{
for (std::function<void(T...)> subscriber : _subscribers)
{
}
}
I hope now this is a valid question cause I'm losing my mind behind this

What is wrong with the obvious way?
void Notify(T... args)
{
// note: no need to write the type if it's quite long
// note: & means the std::function isn't copied
for (auto const& subscriber : _subscribers)
{
subscriber(args...);
}
}

Related

Where to place an actor within the state pattern?

I have problems finding the right place for an actor and a timer used in a state machine.
I found some inspiration from this site about the state pattern:
State Design Pattern in Modern C++ and created a small example:
Simple door state machine
There might be more transitions possible but I kept it short and simple.
class Door
{
void open() {}
void close() {}
};
Events:
class EventOpenDoor
{
public:
OpenDoor(Door* door) : m_pDoor(door) {}
Door* m_pDoor;
};
class EventOpenDoorTemporary
{
public:
EventOpenDoorTemporary(Door* door) : m_pDoor(door) {}
Door* m_pDoor;
};
class EventOpenDoorTimeout
{
public:
EventOpenDoorTimeout(Door* door) : m_pDoor(door) {}
Door* m_pDoor;
};
class EventCloseDoor
{
public:
EventCloseDoor(Door* door) : m_pDoor(door) {}
Door* m_pDoor;
};
using Event = std::variant<EventOpenDoor,
EventOpenDoorTemporary,
EventOpenDoorTimeout,
EventCloseDoor>;
States:
class StateClosed {};
class StateOpen {};
class StateTemporaryOpen {};
using State = std::variant<StateClosed,
StateOpen,
StateTemporaryOpen>;
Transitions (not complete):
struct Transitions {
std::optional<State> operator()(StateClosed &s, const EventOpenDoor &e) {
if (e.m_pDoor)
{
e.m_pDoor->open();
}
auto newState = StateOpen{};
return newState;
}
std::optional<State> operator()(StateClosed &s, const EventOpenDoorTemporary &e) {
if (e.m_pDoor)
{
e.m_pDoor->open();
**// start timer here?**
}
auto newState = StateOpen{};
return newState;
}
std::optional<State> operator()(StateTemporaryOpen &s, const EventOpenDoorTimeout &e) {
if (e.m_pDoor)
{
e.m_pDoor->close();
}
auto newState = StateOpen{};
return newState;
}
std::optional<State> operator()(StateTemporaryOpen &s, const EventOpenDoor &e) {
if (e.m_pDoor)
{
e.m_pDoor->open();
**// stop active timer here?**
}
auto newState = StateOpen{};
return newState;
}
/* --- default ---------------- */
template <typename State_t, typename Event_t>
std::optional<State> operator()(State_t &s, const Event_t &e) const {
// "Unknown transition!";
return std::nullopt;
}
};
Door controller:
template <typename StateVariant, typename EventVariant, typename Transitions>
class DoorController {
StateVariant m_curr_state;
void dispatch(const EventVariant &Event)
{
std::optional<StateVariant> new_state = visit(Transitions{this}, m_curr_state, Event);
if (new_state)
{
m_curr_state = *move(new_state);
}
}
public:
template <typename... Events>
void handle(Events... e)
{ (dispatch(e), ...); }
void setState(StateVariant s)
{
m_curr_state = s;
}
};
The events can be triggered by a client which holds an instance to the "DoorController"
door_controller->handle(EventOpenDoor{door*});
In the events I pass a pointer to the door itself so it's available in the transitions. The door is operated within the transitons only.
I have problems now with modelling the 20s timeout/timer. Where to have such a timer, which triggers the transition to close the door?
Having a timer within the door instance means, I have a circular dependency, because in case of a timeout it needs to call "handle()" of the "door_controller".
I can break the circular dependency with a forward declarations.
But is there a better solution?
Maybe I have modelled it not well. I'm open to improving suggetions.
Thanks a lot!
This isn't going to be the best answer, but I have more questions than answers.
Some of your choices seem odd. I presume there's a complicated reason why you're storing state based on a variant rather than using an enum class State{}, for instance.
I also get nervous when I see raw pointers in modern C++. I'd feel a whole lot better with smart pointers.
When I've done state machines, the events I can handle always subclass from a common Event class -- or I might even just use a single class and give it as many distinct data fields are required for the things that I need to handle. It's a little odd that you use unrelated classes and depend on a dispatch method. Does that even work? Aren't you pushing objects onto an event queue? How do you end up calling that dispatch method with random objects?
You don't show your event loop, but maybe you have a state machine without an event loop. Is it a state machine then? Or maybe you didn't show it. Maybe you can have a state machine without an event loop, but I thought the two concepts were tied together.

Chained anonymous object creation on the heap

I'm writing some arduino libraries and would like to improve readability / add some syntactic suggar.
What I would like to do is create objects on the heap in a way that would look like:
Panel panel(
Button( 1 ).on( Click( clickfunc ) ),
Button( 2 ).on( Hold( holdfunc, 1000 ) )
);
(Button, Click, Hold are all classes and internally managed via linked lists (so they aren't constant.))
I tried writing it this way but I stumbled over problems with references to temporaries.
Currently I can use:
Button button1( 1 ), button2( 2 );
Click theClick( clickFunction );
Hold theHold( holdFunction, 1000 );
Panel( button1.on( theClick ), button2.on( theHold ) );
but this is not nearly as readable as the above and tends to be error-prone because you have to stay alert and don't put e.g. theClick on another button which would break the linked list.
Some heavily shortened excerpts from the classes like they are now.
class Button {
Handler *_first;
Button( int no ){...}
Button & on( Handler &handler ){
handler._next = _first;
_first = &handler;
return *this;
}
void handle( int oldValue, int newValue ) {
Handler *handler;
for( handler = _first; handler; handler = handler->_next ){
handler->handle( oldValue, newValue );
}
}
}
class Handler {
Handler *_next;
virtual void handle( int oldValue, int newValue ) = 0;
...
}
class Click : public Handler {
...
}
class Hold : public Handler {
...
}
Note that this doesn't necessarily needs to stay this way. The goal is to provide a library where its user doesn't need to know to much about its inner working but has a simple/clean interface.
If you have problem with dangling references with the code above, I suspect you are making a linked list that create references (or pointer) that points to those element on the stack.
I suspect also that your signature looks like this:
Button& on(const Event& event) { /* ... */ }
To help you with your problem, I suggest to change the signature of your on function to something like this:
template<typename EventType>
Button& on(EventType&& event) {
}
That way, you can actually forward the object into the heap, and use some form of type easure to put it into your linked list:
struct Handler {
virtual void handle(int oldValue, int newValue) = 0;
// Defaulted virtual destructor
virtual ~Handler() = default;
};
template<typename T>
struct HandlerImpl : Handler {
// constructors
HandlerImpl(T h) : handler{std::forward<T>(h)} {}
void handle(int oldValue, int newValue) {
handler.handle(oldValue, newValue);
}
// We use the compiler generated destructor
private:
remove_rvalue_reference_t<T> handler;
};
template<typename HandlerType>
Button& on(HandlerType&& event) {
// See the code example below
}
What changes in the rest of your code?
Well, now both syntax you posted are supported. The first syntax will move and hold the variable. The second syntax will only hold references to the events and will assume that the lifetime of the event are equal or bigger of those of the button.
Also, Click and Hold don't need to extend any class nor need virtual function or virtual destructors.
If you don't want the second syntax to hold references and use copy instead, replace remove_rvalue_reference_t by std::remove_reference_t.
This pattern I showed you can be applied for Button, and for any widget type you want.
Here's how remove_rvalue_reference_t is implemented:
template<typename T> struct remove_rvalue_reference { using type = T; };
template<typename T> struct remove_rvalue_reference<T&&> { using type = T; };
template<typename T> using remove_rvalue_reference_t = typename remove_rvalue_reference<T>::type;
Since you have posted an example of your code, I can now help you transform it so it can work with the code above.
First, liked list are slow, and hand rolled liked list are worse. I strongly suggest you to use std::vector. Secondly, std::unique_ptr is the preferred way to hold owning pointers. So, just by following this and the steps mentioned above, your code should look like this:
struct Button {
std::vector<std::unique_ptr<Handler>> _handlers;
Button(int no) { /* ... */ }
// This function will work for any type that
// happen to have an `handle` function.
template<typename H> // <--- H is the handler type
Button& on(H&& handler) { // H&& in this case means forwarding reference.
// We add (emplace) a new HandlerImpl, allocated on the heap using `std::make_unique`
_handlers.emplace_back(
std::make_unique<HandlerImpl<H>>(std::forward<H>(handler))
);
return *this;
}
void handle(int oldValue, int newValue) {
// We use a range for loop here to iterate on the vector
for (auto&& handler : _handlers) {
handler->handle(oldValue, newValue);
}
}
};
// We do not extends anything
struct Click {
// Notice that the function is not virtual
void handle(int oldVal, int newVal) {/* ... */}
};
struct Hold {
void handle(int oldVal, int newVal) {/* ... */}
};
Here's a live example at Coliru

C++: Applying the Composite pattern

I am trying to apply the Composite pattern, so I need to create a Leaf class and a Composite class, both inheriting from the same Component class. In order for any of my Components to perform their duty they need to ask help from a single Helper object. We have the following
struct Helper {
void provide_help();
};
struct Component {
Component(Helper* helper)
: m_helper(helper) {
}
virtual void operation() = 0;
// the call_for_help function will be used by subclasses of Component to implement Component::operation()
void call_for_help() {
m_helper->provide_help();
}
private:
Helper* m_helper;
};
And here are two different Leaf subclasses:
struct Leaf1
: Component {
Leaf1(Helper* helper)
: Component(helper) {
}
void operation() override {
call_for_help();
operation1();
}
void operation1();
};
struct Leaf2
: Component {
Leaf2(Helper* helper)
: Component(helper) {
}
void operation() override {
call_for_help();
operation2();
}
void operation2();
};
So far, so good. Now the Composite class is giving me grief. The typical implementation is as follows
struct Composite
: Component {
Composite(Helper* helper)
: Component(helper) {
}
void operation() override {
for (auto el : m_children) el->operation();
}
private:
std::vector<Component*> m_children;
};
which by going through the m_children one by one and calling operation on each essentially calls the helper function multiple times, even though one call is enough for all children. Ideally, if the m_children consisted, say, of a Leaf1 and a Leaf2, I would like somehow the Composite operation to call the helper function only once and then call in succession Leaf1::operation1() and then Leaf2::operation2(). Is there any way to achieve what I need? Alternative designs are welcome. I hope my question makes sense. Thanks in advance!
You want a polymorphic operation but you are adding more responability to the method (calling the helper). It's better to separate these two things.
struct Component {
void call_operation(){
call_for_help();
operation();
}
virtual void operation() = 0;
void call_for_help();
};
Remove the call_for_help() from leaf::operation() (making operation1, operation2 redundant, polymorphism) and the rest should work fine.
You can even hide operation() from your public interface, you'll need friendship with your Composite in that case.
As it could happen at any level, one approach could be to handle this at the level of the helper.
A sketch of the approach would be:
class Helper {
bool composite_help = false;
bool help_provided;
public:
void provide_help() {
if ((composite_help && !help_provided) || !composite_help) {
//TO DO: provide help
help_provided = true;
}
}
void start_composite_help() {
composite_help = true;
help_provided = false;
}
void end_composite_help() {
composite_help = false;
}
};
The principle is that the call for help performed by individual components works as before. But when the composite calls for help, you take preacutions to make sure that the call is performed only once:
void operation() override {
m_helper->start_composite_help();
for (auto el : m_children) el->operation();
m_helper->start_composite_help();
}
As said, this is only a sketch: the code provided as such will not work as soon as you have several levels of composites. So this needs to be improved:
instead of a bool composite_help you'd need a counter, which gets incremented when entering a composite operation and decremented when you exit it. In this case, the counter would go back to 0 (re-enabling help) only when the last level of composte has finished its job.
may be the helper performs different operations to provide help. So you could also imagine to have a "transaction id" that uniquely identifies a group of related operations, and you manage the counter not for the helper overall, in a map of active transactions.
finally, the start/end is not so nice. A RAII helper to the helper could make the whole setup more robust (for example when an exception breaks the normal execution flow.)
I think this problem would be better solved with a combination of Composite and Mediator.
Heads up! I'll show you a different version of the mediator pattern, which is not the same as the canonical version.
It's not of the business of your composite structure to know if a helper was called or not. You'd better do this using some kind of event handler.
Since you have only one helper, you could try like this:
class Helper {
public:
void callHelper() { std::cout << "Helper called" << std::endl; }
};
class Mediator {
private:
std::map<std::string, std::vector<Helper>> subscribers;
int updateLimit = -1;
int currentUpdateCount = 0;
void resetUpdateCount() {
currentUpdateCount = 0;
}
public:
Mediator(){}
void subscribe(std::string evt, Helper helper) {
subscribers[evt].push_back(helper);
}
void update(std::string evt) {
for (auto& h: subscribers[evt]) {
h.callHelper();
}
}
void setUpdateLimit(int i) {
updateLimit = i;
resetUpdateCount();
}
void removeUpdateLimit() {
updateLimit = -1;
resetUpdateCount();
}
int getUpdateLimit() {
return updateLimit;
}
void updateLimited(std::string evt) {
if (updateLimit < 0 || currentUpdateCount < updateLimit) {
update(evt);
currentUpdateCount++;
}
}
};
int main(int argc, const char *argv[])
{
Mediator m;
Helper h1, h2;
m.subscribe("bar", h1);
m.setUpdateLimit(1);
// Will be called only once
m.updateLimited("bar");
m.updateLimited("bar");
m.updateLimited("bar");
m.removeUpdateLimit();
return 0;
}
Using it:
Mediator m;
Helper h1, h2;
m.subscribe("bar", h1);
m.setUpdateLimit(1);
// Will be called only once
m.updateLimited("bar");
m.updateLimited("bar");
m.updateLimited("bar");
m.removeUpdateLimit();
So, here is what you do to integrate this to you composite structure. Remove the helper from you nodes, add the Mediator to the base class:
struct Component {
Component(Mediator& mediator)
: m_helper(mediator) {
}
virtual void operation() = 0;
// the call_for_help function will be used by subclasses of Component to implement Component::operation()
void notify() {
m_mediator->updateFiltered(Component::updateEventName);
}
static std::string updateEventName;
private:
Mediator& m_mediator;
};
std::string Component::updateEventName = "update.composite";
struct Leaf1
: Component {
Leaf1(Helper* helper)
: Component(helper) {
}
void operation() override {
notify();
operation1();
}
void operation1();
};
Using it:
Mediator m;
Helper h;
Composite c(m);
Leaf1 l1(m), l2(m);
c.add(l1);
c.add(l2);
m.subscribe(Component::updateEventName, h);
m.setUpdateLimit(1);
// Will be called only once, even if it has childrens
c.update();
m.removeUpdateLimit();
IMPORTANT: This solution is suboptimal, it has some issues, like you having to pass a mediator instance to every node constructor, but it's just a raw idea for you to work on.
Hope it helps!

What would be the best way to implement callback in C++

I am interested in learning how others design their software. I have used different solutions on different projects, but I have felt that I could have done it better. My implementations involved use of delegates and observers, but today I couldn't resist asking you how you would write it.
Let's assume that we have the following :
class Sensor
{
...
public:
void sensorTriggered();
};
Class Device
{
...
public:
void notifyChangesFromHardware(unsigned int inNotificationInfo);
protected:
Sensor *fireAlarm_;
};
int main()
{
Device someDevice;
return 0;
}
How would you design it if you wanted to call "Device::notifyChangesFromHardware"
from the Sensor object (fireAlarm_)?
Thank you
I would use function pointers or function object:
struct Notifier_Base
{
virtual void notify(void) = 0;
};
class Sensor
{
std::vector<Notifier_Base *> notifiers;
void publish(void)
{
std::vector<Notifier_Base *>::iterator iter;
for (iter = notifiers.begin();
iter != notifiers.end();
++iter)
{
(*iter)->notify();
}
};
See design patterns: Publisher / Consumer, Publisher / subscriber.
I would take a look at Boost Signals also like Piotr S. suggests. Also, a simple pattern I've used would look like this in your case:
template<class NotifyDelegate>
class Sensor
{
...
public:
// assumes you only have one notify delegate
Sensor( NotifyDelegate &nd ) : nd_(nd)
{
}
void sensorTriggered()
{
unsigned int notifyInfo = 99;
nd_.notifyChangesFromHardware( notifyInfo );
}
private:
NotifyDelegate &nd_;
};
Class Device
{
...
public:
void notifyChangesFromHardware(unsigned int inNotificationInfo);
};
int main()
{
Device someDevice;
Sensor<Device> someSensor(someDevice);
someSensor.sensorTriggered();
return 0;
}
Take a look at Observer Pattern as well.

What is the right way to switch on the actual type of an object?

I'm writing an xml parser and I need to add objects to a class generically, switching on the actual type of the object. Problem is, I'd like to keep to an interface which is simply addElement(BaseClass*) then place the object correctly.
void E_TableType::addElement(Element *e)
{
QString label = e->getName();
if (label == "state") {
state = qobject_cast<E_TableEvent*>(e);
}
else if (label == "showPaytable") {
showPaytable = qobject_cast<E_VisibleType*>(e);
}
else if (label == "sessionTip") {
sessionTip = qobject_cast<E_SessionTip*>(e);
}
else if (label == "logoffmedia") {
logoffMedia = qobject_cast<E_UrlType*>(e);
}
else {
this->errorMessage(e);
}
}
This is the calling class, an object factory. myElement is an instance of E_TableType.
F_TableTypeFactory::F_TableTypeFactory()
{
this->myElement = myTable = 0;
}
void F_TableTypeFactory::start(QString qname)
{
this->myElement = myTable = new E_TableType(qname);
}
void F_TableTypeFactory::fill(const QString& string)
{
// don't fill complex types.
}
void F_TableTypeFactory::addChild(Element* child)
{
myTable->addElement(child);
}
Element* F_TableTypeFactory::finish()
{
return myElement;
}
void F_TableTypeFactory::addAttributes(const QXmlAttributes &attribs) {
QString tName = attribs.value(QString("id"));
myTable->setTableName(tName);
}
Have you considered using polymorphism here? If a common interface can be implemented by each of your concrete classes then all of this code goes away and things become simple and easy to change in the future. For example:
class Camera {
public:
virtual void Init() = 0;
virtual void TakeSnapshot() = 0;
}
class KodakCamera : Camera {
public:
void Init() { /* initialize a Kodak camera */ };
void TakeSnapshot() { std::cout << "Kodak snapshot"; }
}
class SonyCamera : Camera {
public:
void Init() { /* initialize a Sony camera */ };
void TakeSnapshot() { std::cout << "Sony snapshot"; }
}
So, let's assume we have a system which contains a hardware device, in this case, a camera. Each device requires different logic to take a picture, but the code has to support a system with any supported camera, so we don't want switch statements littered throughout our code. So, we have created an abstract class Camera.
Each concrete class (i.e., SonyCamera, KodakCamera) implementation will incluse different headers, link to different libraries, etc., but they all share a common interface; we just have to decide which one to create up front. So...
std::unique_ptr<Camera> InitCamera(CameraType type) {
std::unique_ptr<Camera> ret;
Camera *cam;
switch(type) {
case Kodak:
cam = new KodakCamera();
break;
case Sony:
cam = new SonyCamera();
break;
default:
// throw an error, whatever
return;
}
ret.reset(cam);
ret->Init();
return ret;
}
int main(...) {
// get system camera type
std::unique_ptr<Camera> cam = InitCamera(cameraType);
// now we can call cam->TakeSnapshot
// and know that the correct version will be called.
}
So now we have a concrete instance that implements Camera. We can call TakeSnapshot without checking for the correct type anywhere in code because it doesn't matter; we know the correct version for the correct hardware will be called. Hope this helped.
Per your comment below:
I've been trying to use polymorphism, but I think the elements differ too much. For example, E_SessionTip has an amount and status element where E_Url just has a url. I could unify this under a property system but then I lose all the nice typing entirely. If you know of a way this can work though, I'm open to suggestions.
I would propose passing the responsibility for writing the XML data to your types which share a common interface. For example, instead of something like this:
void WriteXml(Entity *entity) {
switch(/* type of entity */) {
// get data from entity depending
// on its type and format
}
// write data to XML
}
Do something like this:
class SomeEntity : EntityBase {
public:
void WriteToXml(XmlStream &stream) {
// write xml to the data stream.
// the entity knows how to do this,
// you don't have to worry about what data
// there is to be written from the outside
}
private:
// your internal data
}
void WriteXml(Entity *entity) {
XmlStream str = GetStream();
entity->WriteToXml(stream);
}
Does that work for you? I've done exactly this before and it worked for me. Let me know.
Double-dispatch may be of interest. The table (in your case) would call a virtual method of the base element, which in turns calls back into the table. This second call is made with the dynamic type of the object, so the appropriate overloaded method is found in the Table class.
#include <iostream>
class Table; //forward declare
class BaseElement
{
public:
virtual void addTo(Table* t);
};
class DerivedElement1 : public BaseElement
{
virtual void addTo(Table* t);
};
class DerivedElement2 : public BaseElement
{
virtual void addTo(Table* t);
};
class Table
{
public:
void addElement(BaseElement* e){ e->addTo(this); }
void addSpecific(DerivedElement1* e){ std::cout<<"D1"; }
void addSpecific(DerivedElement2* e){ std::cout<<"D2"; }
void addSpecific(BaseElement* e){ std::cout<<"B"; }
};
void BaseElement::addTo(Table* t){ t->addSpecific(this); }
void DerivedElement1::addTo(Table* t){ t->addSpecific(this); }
void DerivedElement2::addTo(Table* t){ t->addSpecific(this); }
int main()
{
Table t;
DerivedElement1 d1;
DerivedElement2 d2;
BaseElement b;
t.addElement(&d1);
t.addElement(&d2);
t.addElement(&b);
}
output: D1D2B
Have a Look at the Visitor Pattern, it might help you