1 #ifndef MSP_GAME_EVENTBUS_H_
2 #define MSP_GAME_EVENTBUS_H_
6 #include <msp/core/noncopyable.h>
13 struct EventDispatcher
17 EventObserver *observer;
18 std::function<void(const T &)> callback;
21 std::vector<Handler> handlers;
23 void add_observer(EventObserver *obs, std::function<void(const T &)> &&cb)
24 { handlers.emplace_back(obs, std::move(cb)); }
26 void remove_observer(EventObserver *obs)
27 { std::erase_if(handlers, [obs](auto &h){ return h.observer==obs; }); }
29 void dispatch(const T &) const;
30 void dispatch_to(EventObserver &, const T &) const;
34 class EventBus: public NonCopyable
37 using DeleteFunc = void(void *);
38 using RemoveFunc = void(void *, EventObserver &);
42 void *dispatcher = nullptr;
43 DeleteFunc *deleter = nullptr;
44 RemoveFunc *remover = nullptr;
47 std::vector<Dispatcher> dispatchers;
53 static unsigned get_next_id();
57 static unsigned get_event_id();
61 EventDispatcher<T> &get_dispatcher();
65 void add_observer(EventObserver &obs, std::function<void(const T &)> cb)
66 { get_dispatcher<T>().add_observer(&obs, std::move(cb)); }
68 void replace_observer(EventObserver &, EventObserver &);
69 void remove_observer(EventObserver &);
72 void dispatch(const T &) const;
75 void dispatch_to(EventObserver &, const T &) const;
80 void EventDispatcher<T>::dispatch(const T &event) const
82 for(const Handler &h: handlers)
87 void EventDispatcher<T>::dispatch_to(EventObserver &obs, const T &event) const
89 for(const Handler &h: handlers)
96 inline unsigned EventBus::get_event_id()
98 static unsigned id = get_next_id();
103 inline EventDispatcher<T> &EventBus::get_dispatcher()
105 unsigned id = get_event_id<T>();
106 if(dispatchers.size()<=id)
107 dispatchers.resize(id+1);
109 Dispatcher &event = dispatchers[id];
110 if(!event.dispatcher)
112 event.dispatcher = new EventDispatcher<T>;
113 event.deleter = [](void *p){ delete static_cast<EventDispatcher<T> *>(p); };
114 event.remover = [](void *p, EventObserver &o){ static_cast<EventDispatcher<T> *>(p)->remove_observer(&o); };
117 return *static_cast<EventDispatcher<T> *>(event.dispatcher);
121 inline void EventBus::dispatch(const T &event) const
123 unsigned id = get_event_id<T>();
124 if(id<dispatchers.size() && dispatchers[id].dispatcher)
125 static_cast<EventDispatcher<T> *>(dispatchers[id].dispatcher)->dispatch(event);
129 inline void EventBus::dispatch_to(EventObserver &obs, const T &event) const
131 unsigned id = get_event_id<T>();
132 if(id<dispatchers.size() && dispatchers[id].dispatcher)
133 static_cast<EventDispatcher<T> *>(dispatchers[id].dispatcher)->dispatch_to(obs, event);
136 } // namespace Msp::Game