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