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 - 2025 (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 "comms/details/MsgDispatcherOptionsParser.h"
15#include "comms/dispatch.h"
16#include "comms/Message.h"
17#include "comms/traits.h"
19
20#include <type_traits>
21#include <utility>
22
23namespace comms
24{
25
26namespace details
27{
28
29template <class T, class R = void>
30struct EnableIfHasMsgDispatcherTag { using Type = R; };
31
32template <class T, class Enable = void>
33struct HasMsgDispatcherTag
34{
35 static const bool Value = false;
36};
37
38template <class T>
39struct HasMsgDispatcherTag<T, typename EnableIfHasMsgDispatcherTag<typename T::MsgDispatcherTag>::Type>
40{
41 static const bool Value = true;
42};
43
44template <class T>
45constexpr bool hasMsgDispatcherTag()
46{
47 return HasMsgDispatcherTag<T>::Value;
48}
49
50} // namespace details
51
62template <typename... TOptions>
64{
65 using NoForcingTag = comms::details::tag::Tag1<>;
66
67 using ParsedOptionsInternal = details::MsgDispatcherOptionsParser<TOptions...>;
68
69 using Tag =
71 ParsedOptionsInternal::HasForcedDispatch
72 >::template Type<
73 typename ParsedOptionsInternal::ForcedDispatch,
74 NoForcingTag
75 >;
76
77 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
78 static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, NoForcingTag) ->
79 decltype(comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
80 {
81 return comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
82 }
83
84 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
85 static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, NoForcingTag) ->
86 decltype(comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
87 {
88 return comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
89 }
90
91 template <typename TAllMessages, typename TMsg, typename THandler>
92 static auto dispatchInternal(TMsg& msg, THandler& handler, NoForcingTag) ->
93 decltype(comms::dispatchMsg<TAllMessages>(msg, handler))
94 {
95 return comms::dispatchMsg<TAllMessages>(msg, handler);
96 }
97
98 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
99 static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
100 decltype(comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
101 {
102 return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
103 }
104
105 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
106 static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
107 decltype(comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
108 {
109 return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
110 }
111
112 template <typename TAllMessages, typename TMsg, typename THandler>
113 static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
114 decltype(comms::dispatchMsgPolymorphic<TAllMessages>(msg, handler))
115 {
116 return comms::dispatchMsgPolymorphic<TAllMessages>(msg, handler);
117 }
118
119 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
120 static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
121 decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
122 {
123 return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
124 }
125
126 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
127 static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
128 decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
129 {
130 return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
131 }
132
133 template <typename TAllMessages, typename TMsg, typename THandler>
134 static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
135 decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(msg, handler))
136 {
137 return comms::dispatchMsgStaticBinSearch<TAllMessages>(msg, handler);
138 }
139
140 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
141 static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
142 decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
143 {
144 return comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
145 }
146
147 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
148 static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
149 decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
150 {
151 return comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
152 }
153
154 template <typename TAllMessages, typename TMsg, typename THandler>
155 static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
156 decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(msg, handler))
157 {
158 return comms::dispatchMsgLinearSwitch<TAllMessages>(msg, handler);
159 }
160
161 template <typename TAllMessages>
162 static constexpr bool isDispatchPolymorphicInternal(NoForcingTag)
163 {
164 return comms::dispatchMsgTypeIsPolymorphic<TAllMessages>();
165 }
166
167 template <typename TAllMessages, typename TTag>
168 static constexpr bool isDispatchPolymorphicInternal(TTag)
169 {
170 static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
171 return std::is_same<TTag, comms::traits::dispatch::Polymorphic>::value;
172 }
173
174 template <typename TAllMessages>
175 static constexpr bool isDispatchStaticBinSearchInternal(NoForcingTag)
176 {
177 return comms::dispatchMsgTypeIsStaticBinSearch<TAllMessages>();
178 }
179
180 template <typename TAllMessages, typename TTag>
181 static constexpr bool isDispatchStaticBinSearchInternal(TTag)
182 {
183 static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
184 return std::is_same<TTag, comms::traits::dispatch::StaticBinSearch>::value;
185 }
186
187 template <typename TAllMessages>
188 static constexpr bool isDispatchLinearSwitchInternal(NoForcingTag)
189 {
190 return false;
191 }
192
193 template <typename TAllMessages, typename TTag>
194 static constexpr bool isDispatchLinearSwitchInternal(TTag)
195 {
196 static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
197 return std::is_same<TTag, comms::traits::dispatch::LinearSwitch>::value;
198 }
199
200public:
202 using ParsedOptions = ParsedOptionsInternal;
203
205 using MsgDispatcherTag = typename ParsedOptions::ForcedDispatch;
206
217 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
218 static auto dispatch(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler) ->
219 decltype(dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler, Tag()))
220 {
221 return dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler, Tag());
222 }
223
232 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
233 static auto dispatch(TMsgId&& id, TMsg&& msg, THandler&& handler) ->
234 decltype(dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), msg, handler, Tag()))
235 {
236 return dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), msg, handler, Tag());
237 }
238
250 template <typename TAllMessages, typename TMsg, typename THandler>
251 static auto dispatch(TMsg&& msg, THandler&& handler) ->
252 decltype(dispatchInternal<TAllMessages>(msg, handler, Tag()))
253 {
254 return dispatchInternal<TAllMessages>(msg, handler, Tag());
255 }
256
262 template <typename TAllMessages>
263 static constexpr bool isDispatchPolymorphic()
264 {
265 return isDispatchPolymorphicInternal<TAllMessages>(Tag());
266 }
267
273 template <typename TAllMessages>
274 static constexpr bool isDispatchStaticBinSearch()
275 {
276 return isDispatchStaticBinSearchInternal<TAllMessages>(Tag());
277 }
278
284 template <typename TAllMessages>
285 static constexpr bool isDispatchLinearSwitch()
286 {
287 return isDispatchLinearSwitchInternal<TAllMessages>(Tag());
288 }
289};
290
291namespace details
292{
293
294template <typename T>
295struct IsMsgDispatcher
296{
297 static constexpr bool Value = false;
298};
299
300template <typename... TOptions>
301struct IsMsgDispatcher<MsgDispatcher<TOptions...> >
302{
303 static constexpr bool Value = true;
304};
305
306
307} // namespace details
308
311template <typename T>
312constexpr bool isMsgDispatcher()
313{
314 return
315 details::IsMsgDispatcher<T>::Value ||
316 details::hasMsgDispatcherTag<T>();
317}
318
319} // 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:64
static constexpr bool isDispatchPolymorphic()
Compile time inquiry whether polymorphic dispatch tables are generated internally to map message ID t...
Definition MsgDispatcher.h:263
static constexpr bool isDispatchLinearSwitch()
Compile time inquiry whether linear switch dispatch is generated internally to map message ID to actu...
Definition MsgDispatcher.h:285
ParsedOptionsInternal ParsedOptions
Parsed Options.
Definition MsgDispatcher.h:202
constexpr bool isMsgDispatcher()
Compile time check whether the provided class is a variant of comms::MsgDispatcher.
Definition MsgDispatcher.h:312
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:218
typename ParsedOptions::ForcedDispatch MsgDispatcherTag
Class detection tag.
Definition MsgDispatcher.h:205
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:233
static constexpr bool isDispatchStaticBinSearch()
Compile time inquiry whether static binary search dispatch is generated internally to map message ID ...
Definition MsgDispatcher.h:274
static auto dispatch(TMsg &&msg, THandler &&handler) -> decltype(dispatchInternal< TAllMessages >(msg, handler, Tag()))
Dispatch message to its handler.
Definition MsgDispatcher.h:251
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:208
Tag class used to indicate polymorphic dispatch.
Definition traits.h:202
Tag class used to indicate static binary search dispatch.
Definition traits.h:205
Replacement to std::conditional.
Definition type_traits.h:29
This file contains all the classes necessary to properly define message traits.
Replacement to some types from standard type_traits.