COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
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"
21
22namespace comms
23{
24
25namespace details
26{
27
28template <class T, class R = void>
29struct EnableIfHasMsgDispatcherTag { using Type = R; };
30
31template <class T, class Enable = void>
32struct HasMsgDispatcherTag
33{
34 static const bool Value = false;
35};
36
37template <class T>
38struct HasMsgDispatcherTag<T, typename EnableIfHasMsgDispatcherTag<typename T::MsgDispatcherTag>::Type>
39{
40 static const bool Value = true;
41};
42
43template <class T>
44constexpr bool hasMsgDispatcherTag()
45{
46 return HasMsgDispatcherTag<T>::Value;
47}
48
49} // namespace details
50
61template <typename... TOptions>
63{
64 using NoForcingTag = comms::details::tag::Tag1<>;
65
66 using ParsedOptionsInternal = details::MsgDispatcherOptionsParser<TOptions...>;
67
68 using Tag =
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
199public:
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
290namespace details
291{
292
293template <typename T>
294struct IsMsgDispatcher
295{
296 static constexpr bool Value = false;
297};
298
299template <typename... TOptions>
300struct IsMsgDispatcher<MsgDispatcher<TOptions...> >
301{
302 static constexpr bool Value = true;
303};
304
305
306} // namespace details
307
310template <typename T>
311constexpr 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.