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