COMMS
Template library intended to help with implementation of communication protocols.
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 
12 #include "comms/CompileControl.h"
13 #include "comms/Message.h"
14 #include "comms/details/dispatch_impl.h"
15 #include "comms/util/type_traits.h"
16 #include "comms/details/tag.h"
17 
18 COMMS_MSVC_WARNING_PUSH
19 COMMS_MSVC_WARNING_DISABLE(4100) // Disable warning about unreferenced parameters
20 
21 namespace comms
22 {
23 
35 template <
36  typename TAllMessages,
37  typename TId,
38  typename TMsg,
39  typename THandler>
40 auto 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 
63 template <
64  typename TAllMessages,
65  typename TId,
66  typename TMsg,
67  typename THandler>
68 auto 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 
89 template <
90  typename TAllMessages,
91  typename TMsg,
92  typename THandler>
93 auto 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 
115 template <
116  typename TAllMessages,
117  typename TId,
118  typename THandler>
119 bool dispatchMsgTypePolymorphic(TId&& id, THandler& handler)
120 {
121  return
122  details::DispatchMsgTypePolymorphicHelper<>::template
123  dispatch<TAllMessages>(std::forward<TId>(id), handler);
124 }
125 
138 template <
139  typename TAllMessages,
140  typename TId,
141  typename THandler>
142 bool 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 
161 template <
162  typename TAllMessages,
163  typename TId,
164  typename TMsg,
165  typename THandler>
166 auto 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 
192 template <
193  typename TAllMessages,
194  typename TId,
195  typename TMsg,
196  typename THandler>
197 auto 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 
221 template <
222  typename TAllMessages,
223  typename TMsg,
224  typename THandler>
225 auto 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 
252 template <
253  typename TAllMessages,
254  typename TId,
255  typename THandler>
256 bool 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 
278 template <
279  typename TAllMessages,
280  typename TId,
281  typename THandler>
282 bool 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 
298 template <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 
320 template <
321  typename TAllMessages,
322  typename TId,
323  typename TMsg,
324  typename THandler>
325 auto 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 
351 template <
352  typename TAllMessages,
353  typename TId,
354  typename TMsg,
355  typename THandler>
356 auto 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 
382 template <
383  typename TAllMessages,
384  typename TMsg,
385  typename THandler>
386 auto 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 
413 template <
414  typename TAllMessages,
415  typename TId,
416  typename THandler>
417 bool 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 
439 template <
440  typename TAllMessages,
441  typename TId,
442  typename THandler>
443 bool 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 
459 template <typename TMsg, typename THandler>
460 constexpr bool dispatchMsgIsDirect()
461 {
462  return details::dispatchMsgPolymorphicIsCompatibleHandler<typename std::decay<TMsg>::type, typename std::decay<THandler>::type>();
463 }
464 
472 template <typename TMsg, typename THandler>
473 constexpr bool dispatchMsgIsDirect(TMsg&& msg, THandler&& handler)
474 {
475  return dispatchMsgIsDirect<typename std::decay<decltype(msg)>::type, typename std::decay<decltype(handler)>::type>();
476 }
477 
478 namespace details
479 {
480 template <typename TAllMessages>
481 class DispatchMsgHelper
482 {
483 public:
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 
542 private:
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 
659 template <
660  typename TAllMessages,
661  typename TId,
662  typename TMsg,
663  typename THandler>
664 auto 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 
689 template <
690  typename TAllMessages,
691  typename TId,
692  typename TMsg,
693  typename THandler>
694 auto 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 
717 template <
718  typename TAllMessages,
719  typename TMsg,
720  typename THandler>
721 auto dispatchMsg(TMsg& msg, THandler& handler) ->
722  details::MessageInterfaceDispatchRetType<
723  typename std::decay<decltype(handler)>::type>
724 {
726 }
727 
744 template <typename TAllMessages, typename TId, typename THandler>
745 bool dispatchMsgType(TId&& id, THandler& handler)
746 {
747  return details::DispatchMsgHelper<TAllMessages>::dispatchMsgType(std::forward<TId>(id), handler);
748 }
749 
767 template <typename TAllMessages, typename TId, typename THandler>
768 bool dispatchMsgType(TId&& id, std::size_t index, THandler& handler)
769 {
770  return details::DispatchMsgHelper<TAllMessages>::dispatchMsgType(std::forward<TId>(id), index, handler);
771 }
772 
779 template <typename TAllMessages>
781 {
782  return details::DispatchMsgHelper<TAllMessages>::isPolymorphic();
783 }
784 
794 template <typename TAllMessages, typename TMsg, typename THandler>
795 constexpr bool dispatchMsgIsPolymorphic()
796 {
797  return dispatchMsgIsDirect<TMsg, THandler>() || dispatchMsgTypeIsPolymorphic<TAllMessages>();
798 }
799 
807 template <typename TAllMessages, typename TMsg, typename THandler>
808 constexpr 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 
819 template <typename TAllMessages>
821 {
822  return details::DispatchMsgHelper<TAllMessages>::isStaticBinSearch();
823 }
824 
834 template <typename TAllMessages, typename TMsg, typename THandler>
836 {
837  return (!dispatchMsgIsDirect<TMsg, THandler>()) &&
838  dispatchMsgTypeIsStaticBinSearch<TAllMessages>();
839 }
840 
848 template <typename TAllMessages, typename TMsg, typename THandler>
849 constexpr 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 
856 COMMS_MSVC_WARNING_POP
Contains various compiler related definitions.
Contains definition of Message object interface and various base classes for custom messages.
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition: options.h:1459
Main namespace for all classes / functions of COMMS library.
constexpr bool dispatchMsgIsPolymorphic(TMsg &&msg, THandler &&handler)
Similar to other dispatchMsgIsPolymorphic(), but can help in deducing template arguments.
Definition: dispatch.h:808
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
constexpr bool dispatchMsgIsDirect(TMsg &&msg, THandler &&handler)
Similar to other dispatchMsgIsDirect(), but can help in deducing template arguments.
Definition: dispatch.h:473
bool dispatchMsgTypeStaticBinSearch(TId &&id, std::size_t index, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using static binary se...
Definition: dispatch.h:282
constexpr bool dispatchMsgTypeIsPolymorphic()
Compile time check whether the dispatchMsgType() will use "polymorphic" dispatch for provided tuple o...
Definition: dispatch.h:780
bool dispatchMsgTypeLinearSwitch(TId &&id, std::size_t index, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using linear switch be...
Definition: dispatch.h:443
constexpr bool dispatchMsgTypeIsStaticBinSearch()
Compile time check whether the dispatchMsgType() or dispatchMsgType() will use "static binary search"...
Definition: dispatch.h:820
bool dispatchMsgType(TId &&id, std::size_t index, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using either "polymorp...
Definition: dispatch.h:768
auto dispatchMsgPolymorphic(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:93
bool dispatchMsgTypePolymorphic(TId &&id, std::size_t index, THandler &handler)
Dispatch message id into appropriate handle() function in the provided handler using polymorphic beha...
Definition: dispatch.h:142
auto dispatchMsgStaticBinSearch(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:225
constexpr bool dispatchMsgIsStaticBinSearch(TMsg &&msg, THandler &&handler)
Similar to other dispatchMsgIsStaticBinSearch(), but can help in deducing template arguments.
Definition: dispatch.h:849
auto dispatchMsgLinearSwitch(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:386
auto dispatchMsg(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:721
Replacement to some types from standard type_traits.