1 #ifndef MSP_GAME_EVENTBUS_H_
2 #define MSP_GAME_EVENTBUS_H_
12 struct EventDispatcher
16 EventObserver *observer;
17 std::function<void(const T &)> callback;
20 std::vector<Handler> handlers;
22 void add_observer(EventObserver *obs, std::function<void(const T &)> &&cb)
23 { handlers.emplace_back(obs, std::move(cb)); }
25 void remove_observer(EventObserver *obs)
26 { std::erase_if(handlers, [obs](auto &h){ return h.observer==obs; }); }
28 void dispatch(const T &) const;
29 void dispatch_to(EventObserver &, const T &) const;
36 using DeleteFunc = void(void *);
37 using RemoveFunc = void(void *, EventObserver &);
41 void *dispatcher = nullptr;
42 DeleteFunc *deleter = nullptr;
43 RemoveFunc *remover = nullptr;
46 std::vector<Dispatcher> dispatchers;
48 static unsigned get_next_id();
52 static unsigned get_event_id();
56 EventDispatcher<T> &get_dispatcher();
60 void add_observer(EventObserver &obs, std::function<void(const T &)> cb)
61 { get_dispatcher<T>().add_observer(&obs, std::move(cb)); }
63 void replace_observer(EventObserver &, EventObserver &);
64 void remove_observer(EventObserver &);
67 void dispatch(const T &) const;
70 void dispatch_to(EventObserver &, const T &) const;
75 void EventDispatcher<T>::dispatch(const T &event) const
77 for(const Handler &h: handlers)
82 void EventDispatcher<T>::dispatch_to(EventObserver &obs, const T &event) const
84 for(const Handler &h: handlers)
91 inline unsigned EventBus::get_event_id()
93 static unsigned id = get_next_id();
98 inline EventDispatcher<T> &EventBus::get_dispatcher()
100 unsigned id = get_event_id<T>();
101 if(dispatchers.size()<=id)
102 dispatchers.resize(id+1);
104 Dispatcher &event = dispatchers[id];
105 if(!event.dispatcher)
107 event.dispatcher = new EventDispatcher<T>;
108 event.deleter = [](void *p){ delete static_cast<EventDispatcher<T> *>(p); };
109 event.remover = [](void *p, EventObserver &o){ static_cast<EventDispatcher<T> *>(p)->remove_observer(&o); };
112 return *static_cast<EventDispatcher<T> *>(event.dispatcher);
116 inline void EventBus::dispatch(const T &event) const
118 unsigned id = get_event_id<T>();
119 if(id<dispatchers.size() && dispatchers[id].dispatcher)
120 static_cast<EventDispatcher<T> *>(dispatchers[id].dispatcher)->dispatch(event);
124 inline void EventBus::dispatch_to(EventObserver &obs, const T &event) const
126 unsigned id = get_event_id<T>();
127 if(id<dispatchers.size() && dispatchers[id].dispatcher)
128 static_cast<EventDispatcher<T> *>(dispatchers[id].dispatcher)->dispatch_to(obs, event);
131 } // namespace Msp::Game