qb  2.0.0.0
C++17 Actor Framework
qb Issue Watch Star Fork Follow @isndev
Loading...
Searching...
No Matches
router.h
Go to the documentation of this file.
1
28
29#include <mutex>
33
34#ifndef QB_EVENT_ROUTER_H
35#define QB_EVENT_ROUTER_H
36
37namespace qb::router {
38// struct EventExample {
39// using id_type = uint16_t;
40// using id_handler_type = uint32_t;
41//
42// template<typename T>
43// constexpr id_type type_to_id();
44//
45// id_type id;
46// id_handler_type dest;
47// id_handler_type source;
48// };
49
50namespace internal {
51
57class EventPolicy {
58public:
59 EventPolicy() = default;
60
61 ~EventPolicy() = default;
62
63protected:
75 template <typename _Handler, typename _Event>
76 inline void
77 invoke(_Handler &handler, _Event &event) const {
78 if constexpr (has_member_func_is_alive<_Event>::value) {
79 if (handler.is_alive())
80 handler.on(event);
81 } else
82 handler.on(event);
83 }
84
94 template <typename _Event>
95 inline void
96 dispose(_Event &event) const noexcept {
97 if constexpr (!std::is_trivially_destructible_v<_Event>) {
98 if constexpr (has_member_func_is_alive<_Event>::value) {
99 if (!event.is_alive())
100 event.~_Event();
101 } else
102 event.~_Event();
103 }
104 }
105};
106
107} // namespace internal
108
117template <typename _RawEvent, typename _Handler>
118class sesh : public internal::EventPolicy {
119 using _EventId = typename _RawEvent::id_type;
120 using _HandlerId = typename _RawEvent::id_handler_type;
121
122 _Handler &_handler;
123
124public:
125 sesh() = delete;
126
132 explicit sesh(_Handler &handler) noexcept
133 : _handler(handler) {}
134
141 template <bool _CleanEvent = true>
142 void
143 route(_RawEvent &event) {
144 invoke(_handler, event);
145 if constexpr (_CleanEvent)
146 dispose(event);
147 }
148};
149
158template <typename _RawEvent, typename _Handler = void>
159class semh : public internal::EventPolicy {
160 using _EventId = typename _RawEvent::id_type;
161 using _HandlerId = typename _RawEvent::id_handler_type;
162
164
165public:
166 semh() = default;
167
168 ~semh() = default;
169
179 template <bool _CleanEvent = true>
180 void
181 route(_RawEvent &event) noexcept {
182 if constexpr (has_member_func_is_broadcast<_HandlerId>::value) {
183 if (event.getDestination().is_broadcast()) {
184 for (auto &it : _subscribed_handlers)
185 invoke(it.second, event);
186
187 if constexpr (_CleanEvent)
188 dispose(event);
189
190 return;
191 }
192 }
193
194 const auto &it = _subscribed_handlers.find(event.dest);
195 if (likely(it != _subscribed_handlers.cend()))
196 invoke(it->second, event);
197
198 if constexpr (_CleanEvent)
199 dispose(event);
200 }
201
207 void
208 subscribe(_Handler &handler) noexcept {
209 _subscribed_handlers.erase(handler.id());
210 _subscribed_handlers.insert({handler.id(), handler});
211 }
212
218 void
219 unsubscribe(_HandlerId const &id) noexcept {
220 _subscribed_handlers.erase(id);
221 }
222};
223
231template <typename _RawEvent>
232class semh<_RawEvent, void> : public internal::EventPolicy {
233 using _EventId = typename _RawEvent::id_type;
234 using _HandlerId = typename _RawEvent::id_handler_type;
235
242 class IHandlerResolver {
243 public:
244 virtual ~IHandlerResolver() = default;
245
251 virtual void resolve(_RawEvent &event) = 0;
252 };
253
259 template <typename _Handler>
260 class HandlerResolver
261 : public IHandlerResolver
262 , public sesh<_RawEvent, _Handler> {
263 public:
264 HandlerResolver() = delete;
265 ~HandlerResolver() = default;
266
272 explicit HandlerResolver(_Handler &handler) noexcept
273 : sesh<_RawEvent, _Handler>(handler) {}
274
280 void
281 resolve(_RawEvent &event) final {
283 }
284 };
285
287
288public:
289 semh() = default;
290
294 ~semh() noexcept {
295 for (const auto &it : _subscribed_handlers)
296 delete &(it.second);
297 }
298
308 template <bool _CleanEvent = false>
309 void
310 route(_RawEvent &event) const noexcept {
311 if constexpr (has_member_func_is_broadcast<_HandlerId>::value) {
312 if (event.getDestination().is_broadcast()) {
313 for (const auto &it : _subscribed_handlers)
314 it.second.resolve(event);
315
316 if constexpr (_CleanEvent)
317 dispose(event);
318
319 return;
320 }
321 }
322
323 const auto &it = _subscribed_handlers.find(event.getDestination());
324 if (likely(it != _subscribed_handlers.cend()))
325 it->second.resolve(event);
326
327 if constexpr (_CleanEvent)
328 dispose(event);
329 }
330
339 template <typename _Handler>
340 void
341 subscribe(_Handler &handler) noexcept {
342 const auto &it = _subscribed_handlers.find(handler.id());
343 if (it != _subscribed_handlers.cend()) {
344 delete &it->second;
345 _subscribed_handlers.erase(it);
346 }
347 _subscribed_handlers.insert(
348 {handler.id(), *new HandlerResolver<_Handler>(handler)});
349 }
350
356 void
357 unsubscribe(_HandlerId const &id) noexcept {
358 const auto &it = _subscribed_handlers.find(id);
359 if (it != _subscribed_handlers.end()) {
360 delete &it->second;
361 _subscribed_handlers.erase(it);
362 }
363 }
364};
365
375template <typename _RawEvent, typename _Handler, bool _CleanEvent = true>
376class mesh {
377public:
378 using _EventId = typename _RawEvent::id_type;
379 using _HandlerId = typename _RawEvent::id_handler_type;
380
381private:
388 class IEventResolver {
389 public:
390 virtual ~IEventResolver() = default;
391
398 virtual void resolve(_Handler &handler, _RawEvent &event) const = 0;
399 };
400
406 template <typename _Event>
407 class EventResolver
408 : public IEventResolver
409 , public internal::EventPolicy {
410 public:
411 EventResolver() = default;
412
419 void
420 resolve(_Handler &handler, _RawEvent &event) const final {
421 auto &revent = reinterpret_cast<_Event &>(event);
422 invoke(handler, revent);
423 if constexpr (_CleanEvent)
424 dispose(revent);
425 }
426 };
427
428 _Handler &_handler;
430
431public:
432 mesh() = delete;
433
439 explicit mesh(_Handler &handler) noexcept
440 : _handler(handler) {}
441
445 ~mesh() noexcept {
446 unsubscribe();
447 }
448
456 void
457 route(_RawEvent &event) {
458 // /!\ Why do not not protecting this ?
459 // because a dynamic event pushed and not registred
460 // has 100% risk of leaking memory
461 // Todo : may be should add a define to prevent user from this
462 // const auto &it = _registered_events.find(event.getID());
463 // if (likely(it != _registered_events.cend()))
464 // it->second.resolve(event);
465 _registered_events.at(event.getID()).resolve(_handler, event);
466 }
467
475 template <typename _Event>
476 void
478 const auto &it =
479 _registered_events.find(_RawEvent::template type_to_id<_Event>());
480 if (it == _registered_events.cend()) {
481 _registered_events.insert(
482 {_RawEvent::template type_to_id<_Event>(), *new EventResolver<_Event>});
483 }
484 }
485
493 template <typename _Event>
494 void
496 const auto &it =
497 _registered_events.find(_RawEvent::template type_to_id<_Event>());
498 if (it != _registered_events.cend()) {
499 delete &it->second;
500 _registered_events.erase(it);
501 }
502 }
503
509 void
511 for (const auto &it : _registered_events)
512 delete &it.second;
513 _registered_events.clear();
514 }
515};
516
526template <typename _RawEvent, bool _CleanEvent = true, typename _Handler = void>
527class memh {
528public:
529 using _EventId = typename _RawEvent::id_type;
530 using _HandlerId = typename _RawEvent::id_handler_type;
531
532private:
538 class IEventResolver {
539 public:
540 virtual ~IEventResolver() = default;
541
547 virtual void resolve(_RawEvent &event) = 0;
548
554 virtual void unsubscribe(_HandlerId const &id) = 0;
555 };
556
562 template <typename _Event>
563 class EventResolver
564 : public IEventResolver
565 , public semh<_Event, _Handler> {
566 using _HandlerId = typename _RawEvent::id_handler_type;
567
568 public:
572 EventResolver() noexcept
574
580 void
581 resolve(_RawEvent &event) final {
582 auto &revent = reinterpret_cast<_Event &>(event);
584 }
585
591 void
592 unsubscribe(_HandlerId const &id) final {
594 }
595 };
596
598
599public:
600 memh() = default;
601
605 ~memh() noexcept {
606 for (const auto &it : _registered_events)
607 delete &it.second;
608 }
609
617 template <typename _Func>
618 void
619 route(_RawEvent &event, _Func const &onError) const {
620 const auto &it = _registered_events.find(event.getID());
621 if (likely(it != _registered_events.cend()))
622 it->second.resolve(event);
623 else {
624 // std::lock_guard lk(_disposers_mtx);
625 onError(event);
626 //_disposers.at(event.getID())->dispose(&event);
627 };
628 // /!\ Look notice in of mesh router above
629 // _registered_events.at(event.getID()).resolve(event);
630 }
631
638 template <typename _Event>
639 void
640 subscribe(_Handler &handler) {
641 const auto &it =
642 _registered_events.find(_RawEvent::template type_to_id<_Event>());
643 if (it == _registered_events.cend()) {
644 auto &resolver = *new EventResolver<_Event>;
645 resolver.subscribe(handler);
646 _registered_events.insert(
647 {_RawEvent::template type_to_id<_Event>(), resolver});
648 } else {
649 dynamic_cast<EventResolver<_Event> &>(it->second).subscribe(handler);
650 }
651 }
652
659 template <typename _Event>
660 void
661 unsubscribe(_Handler &handler) const {
662 auto const &it =
663 _registered_events.find(_RawEvent::template type_to_id<_Event>());
664 if (it != _registered_events.cend())
665 it->second.unsubscribe(handler.id());
666 }
667
673 void
674 unsubscribe(_Handler const &handler) const {
675 unsubscribe(handler.id());
676 }
677
683 void
684 unsubscribe(_HandlerId const &id) const {
685 for (auto const &it : _registered_events) {
686 it.second.unsubscribe(id);
687 }
688 }
689};
690
699template <typename _RawEvent, bool _CleanEvent>
700class memh<_RawEvent, _CleanEvent, void> {
701public:
702 using _EventId = typename _RawEvent::id_type;
703 using _HandlerId = typename _RawEvent::id_handler_type;
704
705private:
711 class IDisposer {
712 public:
713 virtual ~IDisposer() = default;
714
720 virtual void dispose(_RawEvent *event) = 0;
721 };
722
728 template <typename T>
729 class Disposer : public IDisposer {
730 public:
738 void
739 dispose(_RawEvent *event) final {
740 if constexpr (!std::is_trivially_destructible_v<T>) {
741 reinterpret_cast<T *>(event)->~T();
742 } else {
743 (void) event;
744 }
745 }
746 };
747
749 static inline std::mutex _disposers_mtx;
750
756 class IEventResolver {
757 public:
758 virtual ~IEventResolver() = default;
759
765 virtual void resolve(_RawEvent &event) const = 0;
766
772 virtual void unsubscribe(_HandlerId const &id) = 0;
773 };
774
780 template <typename _Event>
781 class EventResolver
782 : public IEventResolver
783 , public semh<_Event> {
784 public:
788 EventResolver() noexcept
789 : semh<_Event>() {}
790
796 void
797 resolve(_RawEvent &event) const final {
798 auto &revent = reinterpret_cast<_Event &>(event);
800 }
801
807 void
808 unsubscribe(typename _RawEvent::id_handler_type const &id) final {
810 }
811 };
812
814
815public:
823 template <typename T>
824 struct SafeDispose {
829 std::lock_guard lk(_disposers_mtx);
830
831 _disposers.try_emplace(_RawEvent::template type_to_id<T>(),
832 new Disposer<T>());
833 }
834
835 ~SafeDispose() = default;
836 };
837
838 memh() = default;
839
843 ~memh() noexcept {
844 for (const auto &it : _registered_events)
845 delete &it.second;
846 }
847
855 template <typename _Func>
856 void
857 route(_RawEvent &event, _Func const &onError) const {
858 const auto &it = _registered_events.find(event.getID());
859 if (likely(it != _registered_events.cend()))
860 it->second.resolve(event);
861 else {
862 onError(event);
863 if constexpr (_CleanEvent) {
864 std::lock_guard lk(_disposers_mtx);
865 _disposers.at(event.getID())->dispose(&event);
866 }
867 };
868 }
869
877 template <typename _Event, typename _Handler>
878 void
879 subscribe(_Handler &handler) {
880 static const SafeDispose<_Event> o{};
881
882 const auto &it =
883 _registered_events.find(_RawEvent::template type_to_id<_Event>());
884 if (it == _registered_events.cend()) {
885 auto &resolver = *new EventResolver<_Event>;
886 resolver.subscribe(handler);
887 _registered_events.insert(
888 {_RawEvent::template type_to_id<_Event>(), resolver});
889 } else {
890 dynamic_cast<EventResolver<_Event> *>(&(it->second))->subscribe(handler);
891 }
892 }
893
901 template <typename _Event, typename _Handler>
902 void
903 unsubscribe(_Handler const &handler) const {
904 auto const &it =
905 _registered_events.find(_RawEvent::template type_to_id<_Event>());
906 if (it != _registered_events.cend())
907 it->second.unsubscribe(handler.id());
908 }
909
916 template <typename _Handler>
917 void
918 unsubscribe(_Handler const &handler) const {
919 unsubscribe(handler.id());
920 }
921
927 void
928 unsubscribe(_HandlerId const &id) const {
929 for (auto const &it : _registered_events) {
930 it.second.unsubscribe(id);
931 }
932 }
933};
934
935} // namespace qb::router
936
937#endif // QB_EVENT_ROUTER_H
Branch prediction hint utilities for performance optimization.
Base policy for event handling.
Definition router.h:57
void invoke(_Handler &handler, _Event &event) const
Invoke a handler with an event.
Definition router.h:77
void dispose(_Event &event) const noexcept
Dispose of an event if necessary.
Definition router.h:96
void unsubscribe(_HandlerId const &id) const
Unsubscribe a handler by ID from all event types.
Definition router.h:928
void unsubscribe(_Handler const &handler) const
Unsubscribe a handler from all event types.
Definition router.h:918
void route(_RawEvent &event, _Func const &onError) const
Routes an event to the appropriate handlers with error handling.
Definition router.h:857
void unsubscribe(_Handler const &handler) const
Unsubscribe a handler from events of a specific type.
Definition router.h:903
~memh() noexcept
Destructor that cleans up all event resolvers.
Definition router.h:843
void subscribe(_Handler &handler)
Subscribe a handler to events of a specific type.
Definition router.h:879
Multiple-Event Multiple-Handler router (generic version)
Definition router.h:527
void unsubscribe(_Handler &handler) const
Unsubscribe a handler from events of a specific type.
Definition router.h:661
void unsubscribe(_HandlerId const &id) const
Unsubscribe a handler by ID from all event types.
Definition router.h:684
~memh() noexcept
Destructor that cleans up all event resolvers.
Definition router.h:605
void subscribe(_Handler &handler)
Subscribe a handler to events of a specific type.
Definition router.h:640
void route(_RawEvent &event, _Func const &onError) const
Routes an event to the appropriate handlers with error handling.
Definition router.h:619
void unsubscribe(_Handler const &handler) const
Unsubscribe a handler from all event types.
Definition router.h:674
void unsubscribe()
Unsubscribe from all event types.
Definition router.h:510
void route(_RawEvent &event)
Routes an event to the handler.
Definition router.h:457
void subscribe()
Subscribe to events of a specific type.
Definition router.h:477
mesh(_Handler &handler) noexcept
Constructs a MESH router with the given handler.
Definition router.h:439
~mesh() noexcept
Destructor that cleans up all event resolvers.
Definition router.h:445
void unsubscribe()
Unsubscribe from events of a specific type.
Definition router.h:495
~semh() noexcept
Destructor that cleans up all handler resolvers.
Definition router.h:294
void subscribe(_Handler &handler) noexcept
Subscribe a handler to receive events.
Definition router.h:341
void unsubscribe(_HandlerId const &id) noexcept
Unsubscribe a handler by ID.
Definition router.h:357
void route(_RawEvent &event) const noexcept
Routes an event to the appropriate handler.
Definition router.h:310
Single-Event Multiple-Handler router (generic version)
Definition router.h:159
void route(_RawEvent &event) noexcept
Routes an event to the appropriate handler.
Definition router.h:181
void unsubscribe(_HandlerId const &id) noexcept
Unsubscribe a handler by ID.
Definition router.h:219
void subscribe(_Handler &handler) noexcept
Subscribe a handler to receive events.
Definition router.h:208
Single-Event Single-Handler router.
Definition router.h:118
sesh(_Handler &handler) noexcept
Constructs a SESH router with the given handler.
Definition router.h:132
void route(_RawEvent &event)
Routes an event to the handler.
Definition router.h:143
std::unordered_map< K, V, H, E, A > unordered_map
The primary unordered map implementation.
Definition unordered_map.h:90
Event event
Alias for the base Event class.
Definition Event.h:385
bool likely(bool expr)
Hint for branch prediction when a condition is expected to be true.
Definition branch_hints.h:49
Helper to ensure safe disposal of events.
Definition router.h:824
SafeDispose()
Constructor that registers a disposer.
Definition router.h:828
Advanced type traits and metaprogramming utilities for the QB Framework.
Optimized unordered map implementations.