Guest User

Untitled

a guest
Mar 17th, 2018
80
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.25 KB | None | 0 0
  1. #include <iostream>
  2. #include <map>
  3. #include <vector>
  4. #include <functional>
  5. #include <algorithm> // remove and remove_if
  6.  
  7. template <typename T> const uintptr_t class_id() {
  8. return reinterpret_cast<uintptr_t>(&class_id<T>);
  9. }
  10.  
  11. template <typename T> class EventContainer {
  12. T m_Value;
  13. public:
  14. EventContainer(T value): m_Value(value) {}
  15. T get() {
  16. return this->m_Value;
  17. }
  18. };
  19.  
  20. class IEventHandler {
  21. public:
  22. virtual uintptr_t id() = 0;
  23. virtual void handle_ptr(void* eventPtr) = 0;
  24. };
  25.  
  26. template <typename T> class BaseEventHandler: public IEventHandler {
  27. public:
  28. uintptr_t id(){
  29. uintptr_t value = class_id<T>();
  30. return value;
  31. }
  32. void handle_ptr(void* eventPtr) {
  33. auto cast_eventPtr = static_cast<EventContainer<T>*>(eventPtr);
  34. this->handle(cast_eventPtr->get());
  35. }
  36. virtual void handle(T event) = 0;
  37. };
  38.  
  39. template <typename T> class CallbackEventHandler : public BaseEventHandler<T> {
  40. std::function<void(T)> m_Callback;
  41. public:
  42. CallbackEventHandler(std::function<void(T)> callback): m_Callback(callback) {}
  43. void handle(T event) {
  44. this->m_Callback(event);
  45. }
  46. };
  47.  
  48. class EventDispatcher{
  49. typedef std::map<uintptr_t, std::vector<IEventHandler*>> catalog_t;
  50. typedef EventDispatcher::catalog_t::iterator catalog_iterator_t;
  51. typedef std::vector<IEventHandler*> handler_catalog_t;
  52. EventDispatcher::catalog_t m_Catalogs;
  53. public:
  54. template <typename T> EventDispatcher::catalog_iterator_t getIteratorByType() {
  55. uintptr_t eventClassId = class_id<T>();
  56. auto it = this->m_Catalogs.find(eventClassId);
  57. if (it == this->m_Catalogs.end()) {
  58. this->m_Catalogs[eventClassId];
  59. return this->m_Catalogs.find(eventClassId);
  60. } else {
  61. return it;
  62. }
  63. }
  64.  
  65. template <typename T> std::vector<IEventHandler*>& getHandlerByType() {
  66. EventDispatcher::catalog_iterator_t it = this->getIteratorByType<T>();
  67. return (*it).second;
  68. }
  69.  
  70. template <typename T> void dispatch(T event) {
  71. auto handlers = this->getIteratorByType<T>()->second;
  72. auto eventContainer = EventContainer<T>(event);
  73.  
  74. for(auto it = handlers.begin(); it != handlers.end(); ++it) {
  75. (*it)->handle_ptr(static_cast<void*>(&eventContainer));
  76. }
  77. }
  78.  
  79. template <typename T> IEventHandler* on(std::function<void(T)> callback) {
  80. auto callbackContainer = new CallbackEventHandler<T>(callback);
  81. this->subscribe<T>(callbackContainer);
  82. return callbackContainer;
  83. }
  84.  
  85. void unsubscribe(IEventHandler* handler) {
  86. auto class_id = handler->id();
  87. auto& handlers = this->m_Catalogs[class_id];
  88. handlers.erase(std::remove(handlers.begin(), handlers.end(), handler), handlers.end());
  89. }
  90. template <typename T>void subscribe(BaseEventHandler<T>* handler) {
  91. this->getHandlerByType<T>().push_back(handler);
  92. }
  93. };
  94.  
  95. class BigEvent {};
  96.  
  97. int main() {
  98. auto dispatcher = EventDispatcher();
  99.  
  100. auto eventContainer = dispatcher.on<int>([] (int x) {
  101. std::cout << x << std::endl;
  102. });
  103.  
  104. auto eventContainer2 = dispatcher.on<BigEvent>([] (BigEvent ev) {
  105. std::cout << "Big event incoming !!" << std::endl;
  106. });
  107.  
  108. dispatcher.dispatch<int>(5);
  109. dispatcher.unsubscribe(eventContainer);
  110. dispatcher.dispatch(BigEvent());
  111. }
Add Comment
Please, Sign In to add comment