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 - 2026 (C). Alex Robenko. All rights reserved.
3//
4// SPDX-License-Identifier: MPL-2.0
5//
6// This Source Code Form is subject to the terms of the Mozilla Public
7// License, v. 2.0. If a copy of the MPL was not distributed with this
8// file, You can obtain one at http://mozilla.org/MPL/2.0/.
9
13
14#pragma once
15
16#include "comms/details/MsgDispatcherOptionsParser.h"
17#include "comms/dispatch.h"
18#include "comms/Message.h"
19#include "comms/traits.h"
21
22#include <cstddef>
23#include <type_traits>
24#include <utility>
25
26namespace comms
27{
28
29namespace details
30{
31
32template <class T, class R = void>
33struct EnableIfHasMsgDispatcherTag { using Type = R; };
34
35template <class T, class Enable = void>
36struct HasMsgDispatcherTag
37{
38 static const bool Value = false;
39};
40
41template <class T>
42struct HasMsgDispatcherTag<T, typename EnableIfHasMsgDispatcherTag<typename T::MsgDispatcherTag>::Type>
43{
44 static const bool Value = true;
45};
46
47template <class T>
48constexpr bool hasMsgDispatcherTag()
49{
50 return HasMsgDispatcherTag<T>::Value;
51}
52
53} // namespace details
54
65template <typename... TOptions>
67{
68 using NoForcingTag = comms::details::tag::Tag1<>;
69
70 using ParsedOptionsInternal = details::MsgDispatcherOptionsParser<TOptions...>;
71
72 using Tag =
74 ParsedOptionsInternal::HasForcedDispatch
75 >::template Type<
76 typename ParsedOptionsInternal::ForcedDispatch,
77 NoForcingTag
78 >;
79
80 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
81 static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, NoForcingTag) ->
82 decltype(comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
83 {
84 return comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
85 }
86
87 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
88 static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, NoForcingTag) ->
89 decltype(comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
90 {
91 return comms::dispatchMsg<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
92 }
93
94 template <typename TAllMessages, typename TMsg, typename THandler>
95 static auto dispatchInternal(TMsg& msg, THandler& handler, NoForcingTag) ->
96 decltype(comms::dispatchMsg<TAllMessages>(msg, handler))
97 {
98 return comms::dispatchMsg<TAllMessages>(msg, handler);
99 }
100
101 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
102 static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
103 decltype(comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
104 {
105 return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
106 }
107
108 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
109 static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
110 decltype(comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
111 {
112 return comms::dispatchMsgPolymorphic<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
113 }
114
115 template <typename TAllMessages, typename TMsg, typename THandler>
116 static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::Polymorphic) ->
117 decltype(comms::dispatchMsgPolymorphic<TAllMessages>(msg, handler))
118 {
119 return comms::dispatchMsgPolymorphic<TAllMessages>(msg, handler);
120 }
121
122 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
123 static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
124 decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
125 {
126 return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
127 }
128
129 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
130 static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
131 decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
132 {
133 return comms::dispatchMsgStaticBinSearch<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
134 }
135
136 template <typename TAllMessages, typename TMsg, typename THandler>
137 static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::StaticBinSearch) ->
138 decltype(comms::dispatchMsgStaticBinSearch<TAllMessages>(msg, handler))
139 {
140 return comms::dispatchMsgStaticBinSearch<TAllMessages>(msg, handler);
141 }
142
143 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
144 static auto dispatchInternal(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
145 decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler))
146 {
147 return comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler);
148 }
149
150 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
151 static auto dispatchInternal(TMsgId&& id, TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
152 decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), msg, handler))
153 {
154 return comms::dispatchMsgLinearSwitch<TAllMessages>(std::forward<TMsgId>(id), msg, handler);
155 }
156
157 template <typename TAllMessages, typename TMsg, typename THandler>
158 static auto dispatchInternal(TMsg& msg, THandler& handler, comms::traits::dispatch::LinearSwitch) ->
159 decltype(comms::dispatchMsgLinearSwitch<TAllMessages>(msg, handler))
160 {
161 return comms::dispatchMsgLinearSwitch<TAllMessages>(msg, handler);
162 }
163
164 template <typename TAllMessages>
165 static constexpr bool isDispatchPolymorphicInternal(NoForcingTag)
166 {
167 return comms::dispatchMsgTypeIsPolymorphic<TAllMessages>();
168 }
169
170 template <typename TAllMessages, typename TTag>
171 static constexpr bool isDispatchPolymorphicInternal(TTag)
172 {
173 static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
174 return std::is_same<TTag, comms::traits::dispatch::Polymorphic>::value;
175 }
176
177 template <typename TAllMessages>
178 static constexpr bool isDispatchStaticBinSearchInternal(NoForcingTag)
179 {
180 return comms::dispatchMsgTypeIsStaticBinSearch<TAllMessages>();
181 }
182
183 template <typename TAllMessages, typename TTag>
184 static constexpr bool isDispatchStaticBinSearchInternal(TTag)
185 {
186 static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
187 return std::is_same<TTag, comms::traits::dispatch::StaticBinSearch>::value;
188 }
189
190 template <typename TAllMessages>
191 static constexpr bool isDispatchLinearSwitchInternal(NoForcingTag)
192 {
193 return false;
194 }
195
196 template <typename TAllMessages, typename TTag>
197 static constexpr bool isDispatchLinearSwitchInternal(TTag)
198 {
199 static_assert(!std::is_same<TTag, NoForcingTag>::value, "Invalid tag dispatch");
200 return std::is_same<TTag, comms::traits::dispatch::LinearSwitch>::value;
201 }
202
203public:
205 using ParsedOptions = ParsedOptionsInternal;
206
208 using MsgDispatcherTag = typename ParsedOptions::ForcedDispatch;
209
220 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
221 static auto dispatch(TMsgId&& id, std::size_t idx, TMsg& msg, THandler& handler) ->
222 decltype(dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler, Tag()))
223 {
224 return dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), idx, msg, handler, Tag());
225 }
226
235 template <typename TAllMessages, typename TMsgId, typename TMsg, typename THandler>
236 static auto dispatch(TMsgId&& id, TMsg&& msg, THandler&& handler) ->
237 decltype(dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), msg, handler, Tag()))
238 {
239 return dispatchInternal<TAllMessages>(std::forward<TMsgId>(id), msg, handler, Tag());
240 }
241
253 template <typename TAllMessages, typename TMsg, typename THandler>
254 static auto dispatch(TMsg&& msg, THandler&& handler) ->
255 decltype(dispatchInternal<TAllMessages>(msg, handler, Tag()))
256 {
257 return dispatchInternal<TAllMessages>(msg, handler, Tag());
258 }
259
265 template <typename TAllMessages>
266 static constexpr bool isDispatchPolymorphic()
267 {
268 return isDispatchPolymorphicInternal<TAllMessages>(Tag());
269 }
270
276 template <typename TAllMessages>
277 static constexpr bool isDispatchStaticBinSearch()
278 {
279 return isDispatchStaticBinSearchInternal<TAllMessages>(Tag());
280 }
281
287 template <typename TAllMessages>
288 static constexpr bool isDispatchLinearSwitch()
289 {
290 return isDispatchLinearSwitchInternal<TAllMessages>(Tag());
291 }
292};
293
294namespace details
295{
296
297template <typename T>
298struct IsMsgDispatcher
299{
300 static constexpr bool Value = false;
301};
302
303template <typename... TOptions>
304struct IsMsgDispatcher<MsgDispatcher<TOptions...> >
305{
306 static constexpr bool Value = true;
307};
308
309} // namespace details
310
313template <typename T>
314constexpr bool isMsgDispatcher()
315{
316 return
317 details::IsMsgDispatcher<T>::Value ||
318 details::hasMsgDispatcherTag<T>();
319}
320
321} // 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:67
static constexpr bool isDispatchPolymorphic()
Compile time inquiry whether polymorphic dispatch tables are generated internally to map message ID t...
Definition MsgDispatcher.h:266
static constexpr bool isDispatchLinearSwitch()
Compile time inquiry whether linear switch dispatch is generated internally to map message ID to actu...
Definition MsgDispatcher.h:288
ParsedOptionsInternal ParsedOptions
Parsed Options.
Definition MsgDispatcher.h:205
constexpr bool isMsgDispatcher()
Compile time check whether the provided class is a variant of comms::MsgDispatcher.
Definition MsgDispatcher.h:314
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:221
typename ParsedOptions::ForcedDispatch MsgDispatcherTag
Class detection tag.
Definition MsgDispatcher.h:208
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:236
static constexpr bool isDispatchStaticBinSearch()
Compile time inquiry whether static binary search dispatch is generated internally to map message ID ...
Definition MsgDispatcher.h:277
static auto dispatch(TMsg &&msg, THandler &&handler) -> decltype(dispatchInternal< TAllMessages >(msg, handler, Tag()))
Dispatch message to its handler.
Definition MsgDispatcher.h:254
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:209
Tag class used to indicate polymorphic dispatch.
Definition traits.h:203
Tag class used to indicate static binary search dispatch.
Definition traits.h:206
Replacement to std::conditional.
Definition type_traits.h:32
This file contains all the classes necessary to properly define message traits.
Replacement to some types from standard type_traits.