COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
dispatch.h
Go to the documentation of this file.
1//
2// Copyright 2019 - 2024 (C). Alex Robenko. All rights reserved.
3//
4
7
8#pragma once
9
10#include <type_traits>
11
13#include "comms/Message.h"
14#include "comms/details/dispatch_impl.h"
16#include "comms/details/tag.h"
17
18COMMS_MSVC_WARNING_PUSH
19COMMS_MSVC_WARNING_DISABLE(4100) // Disable warning about unreferenced parameters
20
21namespace comms
22{
23
35template <
36 typename TAllMessages,
37 typename TId,
38 typename TMsg,
39 typename THandler>
40auto dispatchMsgPolymorphic(TId&& id, TMsg& msg, THandler& handler) ->
41 details::MessageInterfaceDispatchRetType<
42 typename std::decay<decltype(handler)>::type>
43{
44 using MsgType = typename std::decay<decltype(msg)>::type;
45 static_assert(comms::isMessage<MsgType>(), "msg param must be a valid message");
46 return
47 details::DispatchMsgPolymorphicHelper<>::template
48 dispatch<TAllMessages>(std::forward<TId>(id), msg, handler);
49}
50
63template <
64 typename TAllMessages,
65 typename TId,
66 typename TMsg,
67 typename THandler>
68auto dispatchMsgPolymorphic(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
69 details::MessageInterfaceDispatchRetType<
70 typename std::decay<decltype(handler)>::type>
71{
72 using MsgType = typename std::decay<decltype(msg)>::type;
73 static_assert(comms::isMessage<MsgType>(), "msg param must be a valid message");
74 return
75 details::DispatchMsgPolymorphicHelper<>::template
76 dispatch<TAllMessages>(std::forward<TId>(id), index, msg, handler);
77}
78
89template <
90 typename TAllMessages,
91 typename TMsg,
92 typename THandler>
93auto dispatchMsgPolymorphic(TMsg& msg, THandler& handler) ->
94 details::MessageInterfaceDispatchRetType<
95 typename std::decay<decltype(handler)>::type>
96{
97 using MsgType = typename std::decay<decltype(msg)>::type;
98 static_assert(comms::isMessage<MsgType>(), "msg param must be a valid message");
99 return
100 details::DispatchMsgPolymorphicHelper<>::template
101 dispatch<TAllMessages>(msg, handler);
102}
103
115template <
116 typename TAllMessages,
117 typename TId,
118 typename THandler>
119bool dispatchMsgTypePolymorphic(TId&& id, THandler& handler)
120{
121 return
122 details::DispatchMsgTypePolymorphicHelper<>::template
123 dispatch<TAllMessages>(std::forward<TId>(id), handler);
124}
125
138template <
139 typename TAllMessages,
140 typename TId,
141 typename THandler>
142bool dispatchMsgTypePolymorphic(TId&& id, std::size_t index, THandler& handler)
143{
144 return
145 details::DispatchMsgTypePolymorphicHelper<>::template
146 dispatch<TAllMessages>(std::forward<TId>(id), index, handler);
147}
148
161template <
162 typename TAllMessages,
163 typename TId,
164 typename TMsg,
165 typename THandler>
166auto dispatchMsgStaticBinSearch(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
167 details::MessageInterfaceDispatchRetType<
168 typename std::decay<decltype(handler)>::type>
169{
170 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
171 "All messages in the provided tuple must statically define their numeric ID");
172
173 return
174 details::DispatchMsgStaticBinSearchHelper<>::template dispatch<TAllMessages>(
175 std::forward<TId>(id),
176 index,
177 msg,
178 handler);
179}
180
192template <
193 typename TAllMessages,
194 typename TId,
195 typename TMsg,
196 typename THandler>
197auto dispatchMsgStaticBinSearch(TId&& id, TMsg& msg, THandler& handler) ->
198 details::MessageInterfaceDispatchRetType<
199 typename std::decay<decltype(handler)>::type>
200{
201 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
202 "All messages in the provided tuple must statically define their numeric ID");
203
204 return
205 details::DispatchMsgStaticBinSearchHelper<>::template dispatch<TAllMessages>(
206 std::forward<TId>(id),
207 msg,
208 handler);
209}
210
221template <
222 typename TAllMessages,
223 typename TMsg,
224 typename THandler>
225auto dispatchMsgStaticBinSearch(TMsg& msg, THandler& handler) ->
226 details::MessageInterfaceDispatchRetType<
227 typename std::decay<decltype(handler)>::type>
228{
229 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
230 "All messages in the provided tuple must statically define their numeric ID");
231 using MsgType = typename std::decay<decltype(msg)>::type;
232 static_assert(MsgType::hasGetId(),
233 "The used message object must provide polymorphic ID retrieval function");
234
235 return
236 details::DispatchMsgStaticBinSearchHelper<>::template dispatch<TAllMessages>(
237 msg,
238 handler);
239}
240
252template <
253 typename TAllMessages,
254 typename TId,
255 typename THandler>
256bool dispatchMsgTypeStaticBinSearch(TId&& id, THandler& handler)
257{
258 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
259 "All messages in the provided tuple must statically define their numeric ID");
260
261 return
262 details::DispatchMsgStaticBinSearchHelper<>::template
263 dispatchType<TAllMessages>(std::forward<TId>(id), handler);
264}
265
278template <
279 typename TAllMessages,
280 typename TId,
281 typename THandler>
282bool dispatchMsgTypeStaticBinSearch(TId&& id, std::size_t index, THandler& handler)
283{
284 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
285 "All messages in the provided tuple must statically define their numeric ID");
286
287 return
288 details::DispatchMsgStaticBinSearchHelper<>::template
289 dispatchType<TAllMessages>(std::forward<TId>(id), index, handler);
290}
291
298template <typename TAllMessages, typename TId>
300{
301 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
302 "All messages in the provided tuple must statically define their numeric ID");
303
304 return
305 details::DispatchMsgStaticBinSearchHelper<>::template
306 dispatchTypeCount<TAllMessages>(std::forward<TId>(id));
307}
308
320template <
321 typename TAllMessages,
322 typename TId,
323 typename TMsg,
324 typename THandler>
325auto dispatchMsgLinearSwitch(TId&& id, TMsg& msg, THandler& handler) ->
326 details::MessageInterfaceDispatchRetType<
327 typename std::decay<decltype(handler)>::type>
328{
329 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
330 "All messages in the provided tuple must statically define their numeric ID");
331
332 return
333 details::DispatchMsgLinearSwitchHelper<>::template dispatch<TAllMessages>(
334 std::forward<TId>(id),
335 msg,
336 handler);
337}
338
351template <
352 typename TAllMessages,
353 typename TId,
354 typename TMsg,
355 typename THandler>
356auto dispatchMsgLinearSwitch(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
357 details::MessageInterfaceDispatchRetType<
358 typename std::decay<decltype(handler)>::type>
359{
360 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
361 "All messages in the provided tuple must statically define their numeric ID");
362
363
364 return
365 details::DispatchMsgLinearSwitchHelper<>::template dispatch<TAllMessages>(
366 std::forward<TId>(id),
367 index,
368 msg,
369 handler);
370}
371
382template <
383 typename TAllMessages,
384 typename TMsg,
385 typename THandler>
386auto dispatchMsgLinearSwitch(TMsg& msg, THandler& handler) ->
387 details::MessageInterfaceDispatchRetType<
388 typename std::decay<decltype(handler)>::type>
389{
390 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
391 "All messages in the provided tuple must statically define their numeric ID");
392 using MsgType = typename std::decay<decltype(msg)>::type;
393 static_assert(MsgType::hasGetId(),
394 "The used message object must provide polymorphic ID retrieval function");
395
396 return
397 details::DispatchMsgLinearSwitchHelper<>::template dispatch<TAllMessages>(
398 msg,
399 handler);
400}
401
413template <
414 typename TAllMessages,
415 typename TId,
416 typename THandler>
417bool dispatchMsgTypeLinearSwitch(TId&& id, THandler& handler)
418{
419 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
420 "All messages in the provided tuple must statically define their numeric ID");
421
422 return
423 details::DispatchMsgLinearSwitchHelper<>::template
424 dispatchType<TAllMessages>(std::forward<TId>(id), handler);
425}
426
439template <
440 typename TAllMessages,
441 typename TId,
442 typename THandler>
443bool dispatchMsgTypeLinearSwitch(TId&& id, std::size_t index, THandler& handler)
444{
445 static_assert(details::allMessagesHaveStaticNumId<TAllMessages>(),
446 "All messages in the provided tuple must statically define their numeric ID");
447
448 return
449 details::DispatchMsgLinearSwitchHelper<>::template
450 dispatchType<TAllMessages>(std::forward<TId>(id), index, handler);
451}
452
459template <typename TMsg, typename THandler>
460constexpr bool dispatchMsgIsDirect()
461{
462 return details::dispatchMsgPolymorphicIsCompatibleHandler<typename std::decay<TMsg>::type, typename std::decay<THandler>::type>();
463}
464
472template <typename TMsg, typename THandler>
473constexpr bool dispatchMsgIsDirect(TMsg&& msg, THandler&& handler)
474{
475 return dispatchMsgIsDirect<typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
476}
477
478namespace details
479{
480template <typename TAllMessages>
481class DispatchMsgHelper
482{
483public:
484 template <typename TMsg, typename THandler>
485 static auto dispatchMsg(TMsg& msg, THandler& handler) ->
486 MessageInterfaceDispatchRetType<
487 typename std::decay<decltype(handler)>::type>
488 {
489 return dispatchMsgInternal(msg, handler, HandlerAdjustedTag<TMsg, THandler>());
490 }
491
492 template <typename TId, typename TMsg, typename THandler>
493 static auto dispatchMsg(TId&& id, TMsg& msg, THandler& handler) ->
494 MessageInterfaceDispatchRetType<
495 typename std::decay<decltype(handler)>::type>
496 {
497 return dispatchMsgInternal(std::forward<TId>(id), msg, handler, HandlerAdjustedTag<TMsg, THandler>());
498 }
499
500 template <typename TId, typename TMsg, typename THandler>
501 static auto dispatchMsg(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
502 MessageInterfaceDispatchRetType<
503 typename std::decay<decltype(handler)>::type>
504 {
505 return dispatchMsgInternal(std::forward<TId>(id), index, msg, handler, HandlerAdjustedTag<TMsg, THandler>());
506 }
507
508 template <typename TId, typename THandler>
509 static bool dispatchMsgType(TId&& id, THandler& handler)
510 {
511 return dispatchMsgTypeInternal(std::forward<TId>(id), handler, Tag<>());
512 }
513
514 template <typename TId, typename THandler>
515 static bool dispatchMsgType(TId&& id, std::size_t index, THandler& handler)
516 {
517 return dispatchMsgTypeInternal(std::forward<TId>(id), index, handler, Tag<>());
518 }
519
520 static constexpr bool isPolymorphic()
521 {
522 return std::is_same<Tag<>, PolymorphicTag<> >::value;
523 }
524
525 static constexpr bool isStaticBinSearch()
526 {
527 return std::is_same<Tag<>, StaticBinSearchTag<> >::value;
528 }
529
530 template <typename TMsg, typename THandler>
531 static constexpr bool isDirect()
532 {
533 return dispatchMsgIsDirect<TMsg, THandler>();
534 }
535
536 template <typename TMsg, typename THandler>
537 static constexpr bool isDirect(TMsg&& msg, THandler&& handler)
538 {
539 return isDirect<typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
540 }
541
542private:
543 template <typename... TParams>
544 using PolymorphicTag = comms::details::tag::Tag1<>;
545
546 template <typename... TParams>
547 using StaticBinSearchTag = comms::details::tag::Tag2<>;
548
549 template <typename...>
550 using Tag =
551 typename comms::util::LazyShallowConditional<
552 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>())
553 >::template Type<
554 PolymorphicTag,
555 StaticBinSearchTag
556 >;
557
558 template <typename TMsgBase, typename THandler>
559 using HandlerAdjustedTag =
560 typename comms::util::LazyShallowConditional<
561 dispatchMsgIsDirect<TMsgBase, THandler>()
562 >::template Type<
563 PolymorphicTag,
564 Tag
565 >;
566
567 template <typename TMsg, typename THandler, typename... TParams>
568 static auto dispatchMsgInternal(TMsg& msg, THandler& handler, PolymorphicTag<TParams...>) ->
569 MessageInterfaceDispatchRetType<
570 typename std::decay<decltype(handler)>::type>
571 {
572 return comms::dispatchMsgPolymorphic<TAllMessages>(msg, handler);
573 }
574
575 template <typename TMsg, typename THandler, typename... TParams>
576 static auto dispatchMsgInternal(TMsg& msg, THandler& handler, StaticBinSearchTag<TParams...>) ->
577 MessageInterfaceDispatchRetType<
578 typename std::decay<decltype(handler)>::type>
579 {
580 return comms::dispatchMsgStaticBinSearch<TAllMessages>(msg, handler);
581 }
582
583 template <typename TId, typename TMsg, typename THandler, typename... TParams>
584 static auto dispatchMsgInternal(TId&& id, TMsg& msg, THandler& handler, PolymorphicTag<TParams...>) ->
585 MessageInterfaceDispatchRetType<
586 typename std::decay<decltype(handler)>::type>
587 {
588 return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TId>(id), msg, handler);
589 }
590
591 template <typename TId, typename TMsg, typename THandler, typename... TParams>
592 static auto dispatchMsgInternal(TId&& id, TMsg& msg, THandler& handler, StaticBinSearchTag<TParams...>) ->
593 MessageInterfaceDispatchRetType<
594 typename std::decay<decltype(handler)>::type>
595 {
596 return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TId>(id), msg, handler);
597 }
598
599 template <typename TId, typename TMsg, typename THandler, typename... TParams>
600 static auto dispatchMsgInternal(TId&& id, std::size_t index, TMsg& msg, THandler& handler, PolymorphicTag<TParams...>) ->
601 MessageInterfaceDispatchRetType<
602 typename std::decay<decltype(handler)>::type>
603 {
604 return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TId>(id), index, msg, handler);
605 }
606
607 template <typename TId, typename TMsg, typename THandler, typename... TParams>
608 static auto dispatchMsgInternal(TId&& id, std::size_t index, TMsg& msg, THandler& handler, StaticBinSearchTag<TParams...>) ->
609 MessageInterfaceDispatchRetType<
610 typename std::decay<decltype(handler)>::type>
611 {
612 return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TId>(id), index, msg, handler);
613 }
614
615 template <typename TId, typename THandler, typename... TParams>
616 static bool dispatchMsgTypeInternal(TId&& id, THandler& handler, PolymorphicTag<TParams...>)
617 {
618 return comms::dispatchMsgTypePolymorphic<TAllMessages>(std::forward<TId>(id), handler);
619 }
620
621 template <typename TId, typename THandler, typename... TParams>
622 static bool dispatchMsgTypeInternal(TId&& id, THandler& handler, StaticBinSearchTag<TParams...>)
623 {
624 return comms::dispatchMsgTypeStaticBinSearch<TAllMessages>(std::forward<TId>(id), handler);
625 }
626
627 template <typename TId, typename THandler, typename... TParams>
628 static bool dispatchMsgTypeInternal(TId&& id, std::size_t index, THandler& handler, PolymorphicTag<TParams...>)
629 {
630 return comms::dispatchMsgTypePolymorphic<TAllMessages>(std::forward<TId>(id), index, handler);
631 }
632
633 template <typename TId, typename THandler, typename... TParams>
634 static bool dispatchMsgTypeInternal(TId&& id, std::size_t index, THandler& handler, StaticBinSearchTag<TParams...>)
635 {
636 return comms::dispatchMsgTypeStaticBinSearch<TAllMessages>(std::forward<TId>(id), index, handler);
637 }
638};
639
640} // namespace details
641
659template <
660 typename TAllMessages,
661 typename TId,
662 typename TMsg,
663 typename THandler>
664auto dispatchMsg(TId&& id, TMsg& msg, THandler& handler) ->
665 details::MessageInterfaceDispatchRetType<
666 typename std::decay<decltype(handler)>::type>
667{
668 return details::DispatchMsgHelper<TAllMessages>::dispatchMsg(std::forward<TId>(id), msg, handler);
669}
670
689template <
690 typename TAllMessages,
691 typename TId,
692 typename TMsg,
693 typename THandler>
694auto dispatchMsg(TId&& id, std::size_t index, TMsg& msg, THandler& handler) ->
695 details::MessageInterfaceDispatchRetType<
696 typename std::decay<decltype(handler)>::type>
697{
698 return details::DispatchMsgHelper<TAllMessages>::dispatchMsg(std::forward<TId>(id), index, msg, handler);
699}
700
717template <
718 typename TAllMessages,
719 typename TMsg,
720 typename THandler>
721auto dispatchMsg(TMsg& msg, THandler& handler) ->
722 details::MessageInterfaceDispatchRetType<
723 typename std::decay<decltype(handler)>::type>
724{
725 return details::DispatchMsgHelper<TAllMessages>::dispatchMsg(msg, handler);
726}
727
744template <typename TAllMessages, typename TId, typename THandler>
745bool dispatchMsgType(TId&& id, THandler& handler)
746{
747 return details::DispatchMsgHelper<TAllMessages>::dispatchMsgType(std::forward<TId>(id), handler);
748}
749
767template <typename TAllMessages, typename TId, typename THandler>
768bool dispatchMsgType(TId&& id, std::size_t index, THandler& handler)
769{
770 return details::DispatchMsgHelper<TAllMessages>::dispatchMsgType(std::forward<TId>(id), index, handler);
771}
772
779template <typename TAllMessages>
781{
782 return details::DispatchMsgHelper<TAllMessages>::isPolymorphic();
783}
784
794template <typename TAllMessages, typename TMsg, typename THandler>
796{
797 return dispatchMsgIsDirect<TMsg, THandler>() || dispatchMsgTypeIsPolymorphic<TAllMessages>();
798}
799
807template <typename TAllMessages, typename TMsg, typename THandler>
808constexpr bool dispatchMsgIsPolymorphic(TMsg&& msg, THandler&& handler)
809{
810 return dispatchMsgIsPolymorphic<TAllMessages, typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
811}
812
819template <typename TAllMessages>
821{
822 return details::DispatchMsgHelper<TAllMessages>::isStaticBinSearch();
823}
824
834template <typename TAllMessages, typename TMsg, typename THandler>
836{
837 return (!dispatchMsgIsDirect<TMsg, THandler>()) &&
838 dispatchMsgTypeIsStaticBinSearch<TAllMessages>();
839}
840
848template <typename TAllMessages, typename TMsg, typename THandler>
849constexpr bool dispatchMsgIsStaticBinSearch(TMsg&& msg, THandler&& handler)
850{
851 return dispatchMsgIsStaticBinSearch<TAllMessages, typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
852}
853
854} // namespace comms
855
856COMMS_MSVC_WARNING_POP
Contains various compiler related definitions.
Contains definition of Message object interface and various base classes for custom messages.
Main namespace for all classes / functions of COMMS library.
constexpr bool dispatchMsgIsPolymorphic()
Compile time check whether the dispatchMsg() will use "polymorphic" (including "direct") dispatch for...
Definition dispatch.h:795
constexpr bool dispatchMsgIsDirect()
Compile time check whether the message object can use its own polymorphic dispatch() (see Polymorphic...
Definition dispatch.h:460
auto dispatchMsg(TId &&id, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using either "poly...
Definition dispatch.h:664
auto dispatchMsgStaticBinSearch(TId &&id, std::size_t index, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using static binar...
Definition dispatch.h:166
bool dispatchMsgTypePolymorphic(TId &&id, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using polymorphic beha...
Definition dispatch.h:119
std::size_t dispatchMsgTypeCountStaticBinSearch(TId &&id)
Count number of message types in the provided tuple that have the requested numeric ID.
Definition dispatch.h:299
bool dispatchMsgTypeLinearSwitch(TId &&id, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using linear switch be...
Definition dispatch.h:417
constexpr bool dispatchMsgIsStaticBinSearch()
Compile time check whether the dispatchMsg() will use "static binary search" dispatch for provided tu...
Definition dispatch.h:835
constexpr bool dispatchMsgTypeIsPolymorphic()
Compile time check whether the dispatchMsgType() will use "polymorphic" dispatch for provided tuple o...
Definition dispatch.h:780
constexpr bool dispatchMsgTypeIsStaticBinSearch()
Compile time check whether the dispatchMsgType() or dispatchMsgType() will use "static binary search"...
Definition dispatch.h:820
auto dispatchMsgPolymorphic(TId &&id, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using polymorphic ...
Definition dispatch.h:40
auto dispatchMsgLinearSwitch(TId &&id, TMsg &msg, THandler &handler) -> details::MessageInterfaceDispatchRetType< typename std::decay< decltype(handler)>::type >
Dispatch message object into appropriate handle() function in the provided handler using linear switc...
Definition dispatch.h:325
bool dispatchMsgType(TId &&id, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using either "polymorp...
Definition dispatch.h:745
bool dispatchMsgTypeStaticBinSearch(TId &&id, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using static binary se...
Definition dispatch.h:256
Replacement to some types from standard type_traits.