Created
November 15, 2016 14:21
-
-
Save lbargaoanu/6f0efa41dc2d190da7f6dc9c282c01c9 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "stdafx.h" | |
#include <iostream> | |
#include <functional> | |
#include <tuple> | |
#include <utility> | |
#include <vector> | |
class IActiveObject { | |
public: | |
void Post(std::function<void(void)> handler) | |
{ | |
handler(); | |
} | |
}; | |
template<typename Events> class EventSource { | |
private: | |
using EventTable = typename Events::EventTable; | |
public: | |
// Connects event handler. | |
template<size_t Event, typename Handler> | |
void Connect(Handler&& handler) { | |
auto& event = std::get<Event>(signals_); | |
event.handlers.emplace_back(std::forward<Handler>(handler), nullptr); | |
} | |
protected: | |
EventSource() = default; | |
// Generates n-ary signal. | |
template<size_t Event, typename... Args> | |
void FireEvent(Args&&... args) const { | |
std::get<Event>(signals_).Fire(std::forward<Args>(args)...); | |
} | |
private: | |
mutable EventTable signals_; | |
}; | |
template<typename Signature> struct EventHandler | |
{ | |
std::function<Signature> handler; | |
IActiveObject* activeObject; | |
EventHandler(std::function<Signature> handler, IActiveObject* activeObject) : handler(handler), activeObject(activeObject) | |
{ | |
} | |
template<typename... Args> | |
void Fire(Args&&... args) const | |
{ | |
IActiveObject localActiveObject; | |
localActiveObject.Post([&]() { | |
handler(std::forward<Args>(args)...); | |
}); | |
} | |
}; | |
template<typename Signature> struct EventDefinition | |
{ | |
std::vector<EventHandler<Signature>> handlers; | |
template<typename... Args> | |
void Fire(Args&&... args) const | |
{ | |
for (auto& item : handlers) | |
{ | |
item.Fire(std::forward<Args>(args)...); | |
} | |
} | |
}; | |
//----------------------------------------------------------------------------- | |
// Example usage. | |
//----------------------------------------------------------------------------- | |
struct MyEvents { | |
enum Event { EventA, EventB }; | |
using EventADef = EventDefinition<void()>; | |
using EventBDef = EventDefinition<void(int, int)>; | |
using EventTable = std::tuple< | |
EventADef, | |
EventBDef | |
>; | |
}; | |
class MySource : public EventSource<MyEvents> { | |
public: | |
void EmitEventA() { | |
std::cout << "EventA signal generated." << std::endl; | |
FireEvent<MyEvents::EventA>(); | |
} | |
int EmitEventB(int foo, int bar) { | |
std::cout << "EventB signal generated. foo = " << foo << " bar = " << bar << std::endl; | |
FireEvent<MyEvents::EventB>(foo, bar); | |
return 0; | |
} | |
}; | |
class MyListener { | |
public: | |
void OnEventA() { | |
std::cout << "OnEventA handler called." << std::endl; | |
} | |
int OnEventB(int foo, int bar) { | |
std::cout << "OnEventB handler called. foo = " << foo << " bar = " << bar << std::endl; | |
return foo * 2; | |
} | |
}; | |
int main() { | |
MySource event_source; | |
MyListener event_listener; | |
// Connect event handlers. | |
event_source.Connect<MyEvents::EventA>([&]() { | |
event_listener.OnEventA(); | |
}); | |
event_source.Connect<MyEvents::EventA>([&]() { | |
event_listener.OnEventA(); | |
}); | |
event_source.Connect<MyEvents::EventB>([&](int foo, int bar) { | |
return event_listener.OnEventB(foo, bar); | |
}); | |
// Fire events. | |
event_source.EmitEventA(); | |
event_source.EmitEventB(3, 4); | |
event_source.EmitEventB(8, 9); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment