1 #ifndef MSP_GAME_EVENTBUS_H_
2 #define MSP_GAME_EVENTBUS_H_
6 #include <msp/core/noncopyable.h>
7 #include "mspgame_api.h"
14 struct EventDispatcher
18 EventObserver *observer;
19 std::function<void(const T &)> callback;
22 std::vector<Handler> handlers;
24 void add_observer(EventObserver *obs, std::function<void(const T &)> &&cb)
25 { handlers.emplace_back(obs, std::move(cb)); }
27 void remove_observer(EventObserver *obs)
28 { std::erase_if(handlers, [obs](auto &h){ return h.observer==obs; }); }
30 void dispatch(const T &) const;
31 void dispatch_to(EventObserver &, const T &) const;
35 class MSPGAME_API EventBus: public NonCopyable
38 using DeleteFunc = void(void *);
39 using RemoveFunc = void(void *, EventObserver &);
43 void *dispatcher = nullptr;
44 DeleteFunc *deleter = nullptr;
45 RemoveFunc *remover = nullptr;
48 std::vector<Dispatcher> dispatchers;
54 static unsigned get_next_id();
58 static unsigned get_event_id();
62 EventDispatcher<T> &get_dispatcher();
66 void add_observer(EventObserver &obs, std::function<void(const T &)> cb)
67 { get_dispatcher<T>().add_observer(&obs, std::move(cb)); }
69 void replace_observer(EventObserver &, EventObserver &);
70 void remove_observer(EventObserver &);
73 void dispatch(const T &) const;
76 void dispatch_to(EventObserver &, const T &) const;
81 void EventDispatcher<T>::dispatch(const T &event) const
83 for(const Handler &h: handlers)
88 void EventDispatcher<T>::dispatch_to(EventObserver &obs, const T &event) const
90 for(const Handler &h: handlers)
97 inline unsigned EventBus::get_event_id()
99 static unsigned id = get_next_id();
104 inline EventDispatcher<T> &EventBus::get_dispatcher()
106 unsigned id = get_event_id<T>();
107 if(dispatchers.size()<=id)
108 dispatchers.resize(id+1);
110 Dispatcher &event = dispatchers[id];
111 if(!event.dispatcher)
113 event.dispatcher = new EventDispatcher<T>;
114 event.deleter = [](void *p){ delete static_cast<EventDispatcher<T> *>(p); };
115 event.remover = [](void *p, EventObserver &o){ static_cast<EventDispatcher<T> *>(p)->remove_observer(&o); };
118 return *static_cast<EventDispatcher<T> *>(event.dispatcher);
122 inline void EventBus::dispatch(const T &event) const
124 unsigned id = get_event_id<T>();
125 if(id<dispatchers.size() && dispatchers[id].dispatcher)
126 static_cast<EventDispatcher<T> *>(dispatchers[id].dispatcher)->dispatch(event);
130 inline void EventBus::dispatch_to(EventObserver &obs, const T &event) const
132 unsigned id = get_event_id<T>();
133 if(id<dispatchers.size() && dispatchers[id].dispatcher)
134 static_cast<EventDispatcher<T> *>(dispatchers[id].dispatcher)->dispatch_to(obs, event);
137 } // namespace Msp::Game