COMMS
Template library intended to help with implementation of communication protocols.
MsgDispatcher.h
Go to the documentation of this file.
1 //
2 // Copyright 2019 - 2024 (C). Alex Robenko. All rights reserved.
3 //
4 // This Source Code Form is subject to the terms of the Mozilla Public
5 // License, v. 2.0. If a copy of the MPL was not distributed with this
6 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 
11 
12 #pragma once
13 
14 #include <type_traits>
15 
16 #include "comms/dispatch.h"
17 #include "comms/Message.h"
18 #include "comms/details/MsgDispatcherOptionsParser.h"
19 #include "comms/traits.h"
20 #include "comms/util/type_traits.h"
21 
22 namespace comms
23 {
24 
25 namespace details
26 {
27 
28 template <class T, class R = void>
29 struct EnableIfHasMsgDispatcherTag { using Type = R; };
30 
31 template <class T, class Enable = void>
32 struct HasMsgDispatcherTag
33 {
34  static const bool Value = false;
35 };
36 
37 template <class T>
38 struct HasMsgDispatcherTag<T, typename EnableIfHasMsgDispatcherTag<typename T::MsgDispatcherTag>::Type>
39 {
40  static const bool Value = true;
41 };
42 
43 template <class T>
44 constexpr bool hasMsgDispatcherTag()
45 {
46  return HasMsgDispatcherTag<T>::Value;
47 }
48 
49 } // namespace details
50 
61 template <typename... TOptions>
63 {
64  using NoForcingTag = comms::details::tag::Tag1<>;
65 
66  using ParsedOptionsInternal = details::MsgDispatcherOptionsParser<TOptions...>;
67 
68  using Tag =
69  typename comms::util::Conditional<
70  ParsedOptionsInternal::HasForcedDispatch
71  >::template Type<
72  typename ParsedOptionsInternal::ForcedDispatch,
73  NoForcingTag
74  >;
75 
76  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
77  static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, NoForcingTag) ->
78  decltype(comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
79  {
80  return comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
81  }
82 
83  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
84  static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, NoForcingTag) ->
85  decltype(comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
86  {
87  return comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
88  }
89 
90  template <typename TAllMessages, typename TMsg, typename THandler>
91  static auto dispatchInternal(TMsg& msg, THandler& handler, NoForcingTag) ->
92  decltype(comms::dispatchMsg<TAllMessages>(msg, handler))
93  {
94  return comms::dispatchMsg<TAllMessages>(msg, handler);
95  }
96 
97  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
98  static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
99  decltype(comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
100  {
101  return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
102  }
103 
104  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
105  static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
106  decltype(comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
107  {
108  return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
109  }
110 
111  template <typename TAllMessages, typename TMsg, typename THandler>
112  static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
113  decltype(comms::dispatchMsgPolymorphic<TAllMessages>(msg, handler))
114  {
115  return comms::dispatchMsgPolymorphic<TAllMessages>(msg, handler);
116  }
117 
118  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
119  static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
120  decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
121  {
122  return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
123  }
124 
125  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
126  static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
127  decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
128  {
129  return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
130  }
131 
132  template <typename TAllMessages, typename TMsg, typename THandler>
133  static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
134  decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(msg, handler))
135  {
136  return comms::dispatchMsgStaticBinSearch<TAllMessages>(msg, handler);
137  }
138 
139  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
140  static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
141  decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
142  {
143  return comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
144  }
145 
146  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
147  static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
148  decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
149  {
150  return comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
151  }
152 
153  template <typename TAllMessages, typename TMsg, typename THandler>
154  static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
155  decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(msg, handler))
156  {
157  return comms::dispatchMsgLinearSwitch<TAllMessages>(msg, handler);
158  }
159 
160  template <typename TAllMessages>
161  static constexpr bool isDispatchPolymorphicInternal(NoForcingTag)
162  {
163  return comms::dispatchMsgTypeIsPolymorphic<TAllMessages>();
164  }
165 
166  template <typename TAllMessages, typename TTag>
167  static constexpr bool isDispatchPolymorphicInternal(TTag)
168  {
169  static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
170  return std::is_same<TTag, comms::traits::dispatch::Polymorphic>::value;
171  }
172 
173  template <typename TAllMessages>
174  static constexpr bool isDispatchStaticBinSearchInternal(NoForcingTag)
175  {
176  return comms::dispatchMsgTypeIsStaticBinSearch<TAllMessages>();
177  }
178 
179  template <typename TAllMessages, typename TTag>
180  static constexpr bool isDispatchStaticBinSearchInternal(TTag)
181  {
182  static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
183  return std::is_same<TTag, comms::traits::dispatch::StaticBinSearch>::value;
184  }
185 
186  template <typename TAllMessages>
187  static constexpr bool isDispatchLinearSwitchInternal(NoForcingTag)
188  {
189  return false;
190  }
191 
192  template <typename TAllMessages, typename TTag>
193  static constexpr bool isDispatchLinearSwitchInternal(TTag)
194  {
195  static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
196  return std::is_same<TTag, comms::traits::dispatch::LinearSwitch>::value;
197  }
198 
199 public:
201  using ParsedOptions = ParsedOptionsInternal;
202 
204  using MsgDispatcherTag = typename ParsedOptions::ForcedDispatch;
205 
216  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
217  static auto dispatch(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler) ->
218  decltype(dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler, Tag()))
219  {
220  return dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler, Tag());
221  }
222 
231  template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
232  static auto dispatch(TMsgId&& id, TMsg&& msg, THandler&& handler) ->
233  decltype(dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), msg, handler, Tag()))
234  {
235  return dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), msg, handler, Tag());
236  }
237 
249  template <typename TAllMessages, typename TMsg, typename THandler>
250  static auto dispatch(TMsg&& msg, THandler&& handler) ->
251  decltype(dispatchInternal<TAllMessages>(msg, handler, Tag()))
252  {
253  return dispatchInternal<TAllMessages>(msg, handler, Tag());
254  }
255 
261  template <typename TAllMessages>
262  static constexpr bool isDispatchPolymorphic()
263  {
264  return isDispatchPolymorphicInternal<TAllMessages>(Tag());
265  }
266 
272  template <typename TAllMessages>
273  static constexpr bool isDispatchStaticBinSearch()
274  {
275  return isDispatchStaticBinSearchInternal<TAllMessages>(Tag());
276  }
277 
283  template <typename TAllMessages>
284  static constexpr bool isDispatchLinearSwitch()
285  {
286  return isDispatchLinearSwitchInternal<TAllMessages>(Tag());
287  }
288 };
289 
290 namespace details
291 {
292 
293 template <typename T>
294 struct IsMsgDispatcher
295 {
296  static constexpr bool Value = false;
297 };
298 
299 template <typename... TOptions>
300 struct IsMsgDispatcher<MsgDispatcher<TOptions...> >
301 {
302  static constexpr bool Value = true;
303 };
304 
305 
306 } // namespace details
307 
310 template <typename T>
311 constexpr bool isMsgDispatcher()
312 {
313  return
314  details::IsMsgDispatcher<T>::Value ||
315  details::hasMsgDispatcherTag<T>();
316 }
317 
318 } // namespace comms
Contains definition of Message object interface and various base classes for custom messages.
An auxiliary class to force a particular way of dispatching message to its handler.
Definition: MsgDispatcher.h:63
static constexpr bool isDispatchPolymorphic()
Compile time inquiry whether polymorphic dispatch tables are generated internally to map message ID t...
Definition: MsgDispatcher.h:262
static constexpr bool isDispatchLinearSwitch()
Compile time inquiry whether linear switch dispatch is generated internally to map message ID to actu...
Definition: MsgDispatcher.h:284
ParsedOptionsInternal ParsedOptions
Parsed Options.
Definition: MsgDispatcher.h:201
constexpr bool isMsgDispatcher()
Compile time check whether the provided class is a variant of comms::MsgDispatcher.
Definition: MsgDispatcher.h:311
static auto dispatch(TMsgId &&id, std::size_t idx, TMsg &msg, THandler &handler) -> decltype(dispatchInternal< TAllMessages >(std::forward< TMsgId >(id), idx, msg, handler, Tag()))
Dispatch message to its handler.
Definition: MsgDispatcher.h:217
typename ParsedOptions::ForcedDispatch MsgDispatcherTag
Class detection tag.
Definition: MsgDispatcher.h:204
static auto dispatch(TMsgId &&id, TMsg &&msg, THandler &&handler) -> decltype(dispatchInternal< TAllMessages >(std::forward< TMsgId >(id), msg, handler, Tag()))
Dispatch message to its handler.
Definition: MsgDispatcher.h:232
static constexpr bool isDispatchStaticBinSearch()
Compile time inquiry whether static binary search dispatch is generated internally to map message ID ...
Definition: MsgDispatcher.h:273
static auto dispatch(TMsg &&msg, THandler &&handler) -> decltype(dispatchInternal< TAllMessages >(msg, handler, Tag()))
Dispatch message to its handler.
Definition: MsgDispatcher.h:250
Contains extra logic to help with dispatching message types and objects.
Main namespace for all classes / functions of COMMS library.
Tag class used to indicate linear switch dispatch.
Definition: traits.h:207
Tag class used to indicate polymorphic dispatch.
Definition: traits.h:201
Tag class used to indicate static binary search dispatch.
Definition: traits.h:204
Replacement to std::conditional.
Definition: type_traits.h:28
This file contains all the classes necessary to properly define message traits.
Replacement to some types from standard type_traits.