COMMS
Template library intended to help with implementation of communication protocols.
Loading...
Searching...
No Matches
DispatchMsgPolymorphicHelper.h
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
10#pragma once
11
12#include "comms/Assert.h"
15#include "comms/details/DispatchMsgIdRetrieveHelper.h"
16#include "comms/details/tag.h"
17#include "comms/Message.h"
18#include "comms/MessageBase.h"
19#include "comms/util/Tuple.h"
21
22#include <algorithm>
23#include <array>
24#include <cstddef>
25#include <limits>
26#include <type_traits>
27#include <utility>
28
29namespace comms
30{
31
32namespace details
33{
34
35template <typename TMsgBase, typename THandler>
36class PolymorphicDirectDispatchMethod
37{
38public:
39 PolymorphicDirectDispatchMethod(const PolymorphicDirectDispatchMethod&) = delete;
40 PolymorphicDirectDispatchMethod& operator=(const PolymorphicDirectDispatchMethod&) = delete;
41
42 virtual auto dispatch(TMsgBase& msg, THandler& handler) const ->
43 MessageInterfaceDispatchRetType<THandler>
44 {
45 return dispatchImpl(msg, handler);
46 }
47
48protected:
49 PolymorphicDirectDispatchMethod() = default;
50 ~PolymorphicDirectDispatchMethod() = default;
51
52 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler) const ->
53 MessageInterfaceDispatchRetType<THandler> = 0;
54};
55
56template <typename TMsgBase, typename THandler, typename TMessage>
57class PolymorphicDirectDispatchMethodImpl : public
58 PolymorphicDirectDispatchMethod<TMsgBase, THandler>
59{
60public:
61 PolymorphicDirectDispatchMethodImpl() = default;
62 PolymorphicDirectDispatchMethodImpl(const PolymorphicDirectDispatchMethodImpl&) = delete;
63 PolymorphicDirectDispatchMethodImpl& operator=(const PolymorphicDirectDispatchMethodImpl&) = delete;
64
65protected:
66 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler) const ->
67 MessageInterfaceDispatchRetType<THandler>
68#ifndef COMMS_COMPILER_GCC47
69 override final
70#endif
71 {
72 static_assert(std::is_base_of<TMsgBase, TMessage>::value, "TMessage must extend TMsgBase");
73 auto& castedMsg = static_cast<TMessage&>(msg);
74 return handler.handle(castedMsg);
75 }
76};
77
78template <typename TMsgBase, typename THandler>
79class PolymorphicBinSearchDispatchMethod
80{
81public:
82 PolymorphicBinSearchDispatchMethod(const PolymorphicBinSearchDispatchMethod&) = delete;
83 PolymorphicBinSearchDispatchMethod& operator=(const PolymorphicBinSearchDispatchMethod&) = delete;
84
85 static_assert(TMsgBase::hasMsgIdType(), "Message interface class must define its id type");
86 using MsgIdParamType = typename TMsgBase::MsgIdParamType;
87 using MsgIdType = typename TMsgBase::MsgIdType;
88
89 virtual MsgIdParamType getId() const
90 {
91 return getIdImpl();
92 }
93
94 virtual auto dispatch(TMsgBase& msg, THandler& handler) const ->
95 MessageInterfaceDispatchRetType<THandler>
96 {
97 return dispatchImpl(msg, handler);
98 }
99
100protected:
101 PolymorphicBinSearchDispatchMethod() = default;
102 ~PolymorphicBinSearchDispatchMethod() = default;
103
104 virtual MsgIdParamType getIdImpl() const = 0;
105 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler) const ->
106 MessageInterfaceDispatchRetType<THandler> = 0;
107};
108
109template <typename TMsgBase, typename THandler, typename TMessage>
110class PolymorphicBinSearchDispatchMethodImpl : public
111 PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>
112{
113 using Base = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
114public:
115 static_assert(TMsgBase::hasMsgIdType(), "Message interface class must define its id type");
116 using MsgIdParamType = typename Base::MsgIdParamType;
117 using MsgIdType = typename Base::MsgIdType;
118
119 PolymorphicBinSearchDispatchMethodImpl() = default;
120 PolymorphicBinSearchDispatchMethodImpl(const PolymorphicBinSearchDispatchMethodImpl&) = delete;
121 PolymorphicBinSearchDispatchMethodImpl& operator=(const PolymorphicBinSearchDispatchMethodImpl&) = delete;
122
123 static MsgIdParamType doGetId()
124 {
125 return dispatchMsgGetMsgId<TMessage>();
126 }
127
128protected:
129
130 virtual MsgIdParamType getIdImpl() const
131#ifndef COMMS_COMPILER_GCC47
132 override final
133#endif
134 {
135 return doGetId();
136 }
137
138 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler) const ->
139 MessageInterfaceDispatchRetType<THandler>
140#ifndef COMMS_COMPILER_GCC47
141 override final
142#endif
143 {
144 static_assert(std::is_base_of<TMsgBase, TMessage>::value, "TMessage must extend TMsgBase");
145 auto& castedMsg = static_cast<TMessage&>(msg);
146 return handler.handle(castedMsg);
147 }
148};
149
150template <typename TMsgBase, typename THandler, std::size_t TSize>
151using PolymorphicDirectDispatchMsgRegistry =
152 std::array<const PolymorphicDirectDispatchMethod<TMsgBase, THandler>*, TSize>;
153
154template <typename TMsgBase, typename THandler, std::size_t TSize>
155using PolymorphicBinSearchDispatchMsgRegistry =
156 std::array<const PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>*, TSize>;
157
158template <typename TMsgBase, typename THandler>
159class PolymorphicDirectDispatchRegistryFiller
160{
161public:
162 using DispatchMethod = PolymorphicDirectDispatchMethod<TMsgBase, THandler>;
163 PolymorphicDirectDispatchRegistryFiller(const DispatchMethod** registry)
164 : m_registry(registry)
165 {
166 }
167
168 template <typename TMessage>
169 void operator()()
170 {
171 static_assert(comms::isMessageBase<TMessage>(), "Must be actual message");
172 static_assert(messageHasStaticNumId<TMessage>(), "Message must define static ID");
173 static const PolymorphicDirectDispatchMethodImpl<TMsgBase, THandler, TMessage> Method{};
174 m_registry[static_cast<std::size_t>(TMessage::doGetId())] = &Method;
175 }
176private:
177 const DispatchMethod** m_registry;
178};
179
180template <typename TMsgBase, typename THandler, std::size_t TSize>
181PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>
182polymorphicDirectDispatchMakeRegistryFiller(
183 PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
184{
185 return PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>(&registry[0]);
186}
187
188template <typename TRegistry, typename TAllMessages>
189class PolymorphicDirectDispatchRegistryInitializer
190{
191public:
192 PolymorphicDirectDispatchRegistryInitializer() = delete;
193 PolymorphicDirectDispatchRegistryInitializer(const PolymorphicDirectDispatchRegistryInitializer&) = delete;
194 explicit PolymorphicDirectDispatchRegistryInitializer(TRegistry& registry)
195 {
196 std::fill(registry.begin(), registry.end(), nullptr);
197 comms::util::tupleForEachType<TAllMessages>(polymorphicDirectDispatchMakeRegistryFiller(registry));
198 }
199};
200
201template <typename TMsgBase, typename THandler>
202class PolymorphicBinSearchDispatchRegistryFiller
203{
204public:
205 using DispatchMethod = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
206 PolymorphicBinSearchDispatchRegistryFiller(const DispatchMethod** registry)
207 : m_registry(registry)
208 {
209 }
210
211 template <typename TMessage>
212 void operator()()
213 {
214 static_assert(comms::isMessageBase<TMessage>(), "Must be actual message");
215 static_assert(messageHasStaticNumId<TMessage>(), "Message must define static ID");
216 static const PolymorphicBinSearchDispatchMethodImpl<TMsgBase, THandler, TMessage> Method{};
217 m_registry[m_idx] = &Method;
218 ++m_idx;
219 }
220
221private:
222 const DispatchMethod** m_registry;
223 std::size_t m_idx = 0U;
224};
225
226template <typename TMsgBase, typename THandler, std::size_t TSize>
227PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>
228polymorphicBinSearchDispatchMakeRegistryFiller(
229 PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
230{
231 return PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>(&registry[0]);
232}
233
234template <typename TRegistry, typename TAllMessages>
235class PolymorphicBinSearchDispatchRegistryInitializer
236{
237public:
238 explicit PolymorphicBinSearchDispatchRegistryInitializer(TRegistry& registry)
239 {
240 std::fill(registry.begin(), registry.end(), nullptr);
241 comms::util::tupleForEachType<TAllMessages>(polymorphicBinSearchDispatchMakeRegistryFiller(registry));
242 }
243};
244
245template <typename TAllMessages, std::size_t TMaxSize>
246class PolymorphicDirectDispatchRegSizeDetect
247{
248 using MsgType = typename std::tuple_element<TMaxSize - 1, TAllMessages>::type;
249 static_assert(comms::isMessageBase<MsgType>(), "Must be actual message");
250 static_assert(messageHasStaticNumId<MsgType>(), "Message must define static numeric ID");
251 static_assert(MsgType::hasMsgIdType(), "Message interface class must define its id type");
252 static const typename MsgType::MsgIdParamType MsgId = MsgType::doGetId();
253public:
254 static const std::size_t Value = static_cast<std::size_t>(MsgId) + 1U;
255};
256
257template <typename TAllMessages>
258class PolymorphicDirectDispatchRegSizeDetect<TAllMessages, 0U>
259{
260public:
261 static const std::size_t Value = 0;
262};
263
264template <typename TAllMessages, typename TMsgBase, typename THandler>
265class DispatchMsgDirectPolymorphicHelper
266{
267public:
268 static_assert(TMsgBase::hasMsgIdType(), "Message interface class must define its id type");
269 using MsgIdParamType = typename TMsgBase::MsgIdParamType;
270 static auto dispatch(MsgIdParamType id, TMsgBase& msg, THandler& handler) ->
271 MessageInterfaceDispatchRetType<
272 typename std::decay<decltype(handler)>::type>
273 {
274 // Access initializer object to ensure it hasn't been erased by the optimizer
275 static_cast<void>(s_initializer);
276
277 using RetType =
278 MessageInterfaceDispatchRetType<
279 typename std::decay<decltype(handler)>::type>;
280
281 auto regIdx = static_cast<std::size_t>(id);
282 if ((s_registry.size() <= regIdx) ||
283 (s_registry[regIdx] == nullptr)) {
284 return static_cast<RetType>(handler.handle(msg));
285 }
286
287 return static_cast<RetType>(s_registry[regIdx]->dispatch(msg, handler));
288 }
289
290private:
291 static const std::size_t RegistrySize =
292 PolymorphicDirectDispatchRegSizeDetect<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
293 using Registry = PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, RegistrySize>;
294 using Initializer = PolymorphicDirectDispatchRegistryInitializer<Registry, TAllMessages>;
295
296 static Registry s_registry;
297 static const Initializer s_initializer;
298};
299
300template <typename TAllMessages, typename TMsgBase, typename THandler>
301typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Registry
302DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_registry;
303
304template <typename TAllMessages, typename TMsgBase, typename THandler>
305const typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Initializer
306DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
307
308template <typename TAllMessages, typename TMsgBase, typename THandler>
309class DispatchMsgBinSearchPolymorphicHelperBase
310{
311protected:
312 static const std::size_t RegistrySize = std::tuple_size<TAllMessages>::value;
313 using Registry = PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, RegistrySize>;
314 using Initializer = PolymorphicBinSearchDispatchRegistryInitializer<Registry, TAllMessages>;
315
316 static Registry s_registry;
317 static Initializer s_initializer;
318};
319
320template <typename TAllMessages, typename TMsgBase, typename THandler>
321typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Registry
322DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_registry;
323
324template <typename TAllMessages, typename TMsgBase, typename THandler>
325typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Initializer
326DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
327
328template <typename TAllMessages, typename TMsgBase, typename THandler>
329class DispatchMsgBinSearchStrongPolymorphicHelper : public
330 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
331{
332 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
333 using Registry = typename Base::Registry;
334public:
335 static_assert(TMsgBase::hasMsgIdType(), "Message interface class must define its id type");
336 using MsgIdParamType = typename TMsgBase::MsgIdParamType;
337 static auto dispatch(MsgIdParamType id, TMsgBase& msg, THandler& handler) ->
338 MessageInterfaceDispatchRetType<
339 typename std::decay<decltype(handler)>::type>
340 {
341 // Access initializer object to ensure it hasn't been erased by the optimizer
342 static_cast<void>(Base::s_initializer);
343
344 using RetType =
345 MessageInterfaceDispatchRetType<
346 typename std::decay<decltype(handler)>::type>;
347
348 auto iter =
349 std::lower_bound(
350 Base::s_registry.begin(), Base::s_registry.end(), id,
351 [](typename Registry::value_type method, MsgIdParamType idParam) -> bool
352 {
353 COMMS_ASSERT(method != nullptr);
354 return method->getId() < idParam;
355 });
356
357 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
358 return static_cast<RetType>(handler.handle(msg));
359 }
360
361 return static_cast<RetType>((*iter)->dispatch(msg, handler));
362 }
363};
364
365template <typename TAllMessages, typename TMsgBase, typename THandler>
366class DispatchMsgBinSearchWeakPolymorphicHelper : public
367 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
368{
369 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
370 using Registry = typename Base::Registry;
371public:
372 template <typename TId>
373 static auto dispatch(TId&& id, std::size_t offset, TMsgBase& msg, THandler& handler) ->
374 MessageInterfaceDispatchRetType<
375 typename std::decay<decltype(handler)>::type>
376 {
377 // Access initializer object to ensure it hasn't been erased by the optimizer
378 static_cast<void>(Base::s_initializer);
379
380 using RetType =
381 MessageInterfaceDispatchRetType<
382 typename std::decay<decltype(handler)>::type>;
383
384 using IdType = typename std::decay<decltype(id)>::type;
385
386 auto lowerIter =
387 std::lower_bound(
388 Base::s_registry.begin(), Base::s_registry.end(), id,
389 [](typename Registry::value_type method, IdType idParam) -> bool
390 {
391 COMMS_ASSERT(method != nullptr);
392 return static_cast<IdType>(method->getId()) < idParam;
393 });
394
395 if ((lowerIter == Base::s_registry.end()) ||
396 (static_cast<IdType>((*lowerIter)->getId()) != id)) {
397 return static_cast<RetType>(handler.handle(msg));
398 }
399
400 auto upperIter =
401 std::upper_bound(
402 lowerIter, Base::s_registry.end(), id,
403 [](IdType idParam, typename Registry::value_type method)
404 {
405 return idParam < static_cast<IdType>(method->getId());
406 }
407 );
408
409 COMMS_ASSERT(lowerIter < upperIter);
410
411 auto dist = static_cast<std::size_t>(upperIter - lowerIter);
412 if (dist <= offset) {
413 return static_cast<RetType>(handler.handle(msg));
414 }
415
416 auto actualIter = lowerIter + offset;
417 return static_cast<RetType>((*actualIter)->dispatch(msg, handler));
418 }
419};
420
421template <typename TElem, bool TIsMessage>
422struct DispatchMsgPolymorphicLastIdRetriever;
423
424template <typename TElem>
425struct DispatchMsgPolymorphicLastIdRetriever<TElem, true>
426{
427 static_assert(messageHasStaticNumId<TElem>(), "TElem must define static numeric id");
428 static const std::size_t Value =
429 static_cast<std::size_t>(TElem::doGetId());
430};
431
432template <typename TElem>
433struct DispatchMsgPolymorphicLastIdRetriever<TElem, false>
434{
435 static const std::size_t Value = std::numeric_limits<std::size_t>::max();
436};
437
438template <typename TAllMessages, std::size_t TCount>
439class DispatchMsgPolymorphicIsDirectSuitable
440{
441 using LastMsg =
442 typename std::tuple_element<
443 std::tuple_size<TAllMessages>::value - 1,
444 TAllMessages
445 >::type;
446
447 static const std::size_t MaxId =
448 DispatchMsgPolymorphicLastIdRetriever<LastMsg, comms::isMessageBase<LastMsg>()>::Value;
449
450 static const std::size_t MaxAllowedId = (TCount * 11) / 10;
451
452public:
453 static const bool Value =
454 (MaxId <= (TCount + 10U)) || (MaxId <= MaxAllowedId);
455};
456
457template <typename TAllMessages>
458class DispatchMsgPolymorphicIsDirectSuitable<TAllMessages, 0U>
459{
460public:
461 static const bool Value = true;
462};
463
464template <typename TAllMessages>
465static constexpr bool dispatchMsgPolymorphicIsDirectSuitable()
466{
467 return
468 allMessagesHaveStaticNumId<TAllMessages>() &&
469 DispatchMsgPolymorphicIsDirectSuitable<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
470}
471
472template <typename...>
473struct DispatchMsgPolymorphicCompatibleHandlerDetector
474{
475 template <typename TMsg, typename THandler>
476 using Type = std::is_base_of<typename TMsg::Handler, THandler>;
477};
478
479template <typename TMsg, typename THandler>
480using DispatchMsgPolymorphicCompatibleHandlerDetectBoolType =
481 typename comms::util::LazyDeepConditional<
482 TMsg::hasDispatch()
483 >::template Type<
484 DispatchMsgPolymorphicCompatibleHandlerDetector,
485 comms::util::FalseType,
486 TMsg, THandler
487 >;
488
489template <typename TMsg, typename THandler>
490constexpr bool dispatchMsgPolymorphicIsCompatibleHandler()
491{
492 return DispatchMsgPolymorphicCompatibleHandlerDetectBoolType<TMsg, THandler>::value;
493}
494
495template <typename ...>
496class DispatchMsgPolymorphicHelper
497{
498 template <typename... TParams>
499 using EmptyTag = comms::details::tag::Tag1<>;
500
501 template <typename... TParams>
502 using DispatchInterfaceTag = comms::details::tag::Tag2<>;
503
504 template <typename... TParams>
505 using DirectTag = comms::details::tag::Tag3<>;
506
507 template <typename... TParams>
508 using StrongBinSearchTag = comms::details::tag::Tag4<>;
509
510 template <typename... TParams>
511 using WeakBinSearchTag = comms::details::tag::Tag5<>;
512
513 template <typename... TParams>
514 using IdInterfaceTag = comms::details::tag::Tag6<>;
515
516 template <typename... TParams>
517 using NoIdInterfaceTag = comms::details::tag::Tag7<>;
518
519 template <typename TAllMessages, typename...>
520 using DirectStrongTag =
521 typename comms::util::LazyShallowConditional<
522 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
523 >::template Type<
524 DirectTag,
525 StrongBinSearchTag
526 >;
527
528 template <typename TAllMessages, typename...>
529 using DirectStrongWeakTag =
530 typename comms::util::LazyShallowConditional<
531 allMessagesAreStrongSorted<TAllMessages>()
532 >::template Type<
533 DirectStrongTag,
534 WeakBinSearchTag,
535 TAllMessages
536 >;
537
538 template <typename TAllMessages, typename TMsgBase, typename THandler, typename...>
539 using Tag =
540 typename comms::util::LazyShallowConditional<
541 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
542 >::template Type<
543 DispatchInterfaceTag,
544 DirectStrongWeakTag,
545 TAllMessages
546 >;
547
548 template <typename TAllMessages, typename TMsgBase, typename THandler, typename...>
549 using AdjustedTag =
550 typename comms::util::LazyShallowConditional<
551 comms::isMessageBase<TMsgBase>()
552 >::template Type<
553 EmptyTag,
554 Tag,
555 TAllMessages, TMsgBase, THandler
556 >;
557
558 template <typename TMsgBase, typename...>
559 using InterfaceDispatchTag =
560 typename comms::util::LazyShallowConditional<
561 TMsgBase::hasGetId()
562 >::template Type<
563 IdInterfaceTag,
564 NoIdInterfaceTag
565 >;
566
567 template <typename TMsgBase, typename THandler, typename...>
568 using PolymorphicCheckDispatchTag =
569 typename comms::util::LazyShallowConditional<
570 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
571 >::template Type<
572 NoIdInterfaceTag,
573 InterfaceDispatchTag,
574 TMsgBase
575 >;
576
577public:
578 template <typename TAllMessages, typename TMsgBase, typename THandler>
579 static auto dispatch(TMsgBase& msg, THandler& handler) ->
580 MessageInterfaceDispatchRetType<
581 typename std::decay<decltype(handler)>::type>
582 {
583
584 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
585 "Message types must be sorted by their ID");
586
587 static_assert(comms::isMessage<TMsgBase>(),
588 "TMsgBase is expected to be message interface class");
589
590 static_assert(TMsgBase::hasMsgIdType(), "Message interface class must define its id type");
591
592 using MsgType = typename std::decay<decltype(msg)>::type;
593 using HandlerType = typename std::decay<decltype(handler)>::type;
594 using IdRetrieveTag =
595 typename comms::util::LazyShallowConditional<
596 comms::isMessageBase<MsgType>()
597 >::template Type<
598 EmptyTag,
599 PolymorphicCheckDispatchTag,
600 MsgType, HandlerType
601 >;
602
603 return dispatchInternal<TAllMessages>(msg, handler, IdRetrieveTag());
604 }
605
606 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler>
607 static auto dispatch(TId&& id, TMsgBase& msg, THandler& handler) ->
608 MessageInterfaceDispatchRetType<
609 typename std::decay<decltype(handler)>::type>
610 {
611 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
612 "Message types must be sorted by their ID");
613
614 static_assert(comms::isMessage<TMsgBase>(),
615 "TMsgBase is expected to be message interface class");
616
617 static_assert(TMsgBase::hasMsgIdType(), "Message interface class must define its id type");
618
619 using MsgType = typename std::decay<decltype(msg)>::type;
620 using HandlerType = typename std::decay<decltype(handler)>::type;
621 return
622 dispatchInternal<TAllMessages>(
623 static_cast<typename MsgType::MsgIdParamType>(id),
624 msg,
625 handler,
626 AdjustedTag<TAllMessages, MsgType, HandlerType>());
627 }
628
629 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler>
630 static auto dispatch(TId&& id, std::size_t offset, TMsgBase& msg, THandler& handler) ->
631 MessageInterfaceDispatchRetType<
632 typename std::decay<decltype(handler)>::type>
633 {
634 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
635 "Message types must be sorted by their ID");
636
637 static_assert(comms::isMessage<TMsgBase>(),
638 "TMsgBase is expected to be message interface class");
639
640 static_assert(TMsgBase::hasMsgIdType(), "Message interface class must define its id type");
641
642 using MsgType = typename std::decay<decltype(msg)>::type;
643 using HandlerType = typename std::decay<decltype(handler)>::type;
644 return
645 dispatchInternal<TAllMessages>(
646 static_cast<typename MsgType::MsgIdParamType>(id),
647 offset,
648 msg,
649 handler,
650 AdjustedTag<TAllMessages, MsgType, HandlerType>());
651 }
652
653private:
654 template <typename TAllMessages, typename TMsgBase, typename THandler, typename... TParams>
655 static auto dispatchInternal(TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
656 decltype(handler.handle(msg))
657 {
658 return handler.handle(msg);
659 }
660
661 template <typename TAllMessages, typename TMsgBase, typename THandler, typename... TParams>
662 static auto dispatchInternal(TMsgBase& msg, THandler& handler, IdInterfaceTag<TParams...>) ->
663 MessageInterfaceDispatchRetType<
664 typename std::decay<decltype(handler)>::type>
665 {
666 typename TMsgBase::MsgIdParamType id = msg.getId();
667 return dispatch<TAllMessages>(id, msg, handler);
668 }
669
670 template <typename TAllMessages, typename TMsgBase, typename THandler, typename... TParams>
671 static auto dispatchInternal(TMsgBase& msg, THandler& handler, NoIdInterfaceTag<TParams...>) ->
672 MessageInterfaceDispatchRetType<
673 typename std::decay<decltype(handler)>::type>
674 {
675 static_assert(TMsgBase::hasDispatch(), "The message must provide polymorphic dispatch");
676 static_assert(std::is_base_of<typename TMsgBase::Handler, THandler>::value,
677 "Incompatible handlers");
678
679 using RetType = MessageInterfaceDispatchRetType<THandler>;
680 return static_cast<RetType>(msg.dispatch(handler));
681 }
682
683 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
684 static auto dispatchInternal(TId&& id, TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
685 decltype(handler.handle(msg))
686 {
687 static_cast<void>(id);
688 return handler.handle(msg);
689 }
690
691 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
692 static auto dispatchInternal(TId&& id, TMsgBase& msg, THandler& handler, DispatchInterfaceTag<TParams...>) ->
693 MessageInterfaceDispatchRetType<
694 typename std::decay<decltype(handler)>::type>
695 {
696 static_cast<void>(id);
697 return dispatchInternal<TAllMessages>(msg, handler, NoIdInterfaceTag<>());
698 }
699
700 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
701 static auto dispatchInternal(TId&& id, TMsgBase& msg, THandler& handler, DirectTag<TParams...>) ->
702 MessageInterfaceDispatchRetType<
703 typename std::decay<decltype(handler)>::type>
704 {
705 using MsgType = typename std::decay<decltype(msg)>::type;
706 using HandlerType = typename std::decay<decltype(handler)>::type;
707
708 return DispatchMsgDirectPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
709 dispatch(std::forward<TId>(id), msg, handler);
710 }
711
712 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
713 static auto dispatchInternal(TId&& id, TMsgBase& msg, THandler& handler, StrongBinSearchTag<TParams...>) ->
714 MessageInterfaceDispatchRetType<
715 typename std::decay<decltype(handler)>::type>
716 {
717 using MsgType = typename std::decay<decltype(msg)>::type;
718 using HandlerType = typename std::decay<decltype(handler)>::type;
719
720 return DispatchMsgBinSearchStrongPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
721 dispatch(std::forward<TId>(id), msg, handler);
722 }
723
724 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
725 static auto dispatchInternal(TId&& id, TMsgBase& msg, THandler& handler, WeakBinSearchTag<TParams...>) ->
726 MessageInterfaceDispatchRetType<
727 typename std::decay<decltype(handler)>::type>
728 {
729 return dispatchInternal<TAllMessages>(std::forward<TId>(id), 0U, msg, handler, WeakBinSearchTag<>());
730 }
731
732 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
733 static auto dispatchInternal(TId&& id, std::size_t offset, TMsgBase& msg, THandler& handler, DispatchInterfaceTag<TParams...>) ->
734 MessageInterfaceDispatchRetType<
735 typename std::decay<decltype(handler)>::type>
736 {
737 static_cast<void>(id);
738 static_cast<void>(offset);
739 static_assert(std::is_base_of<typename TMsgBase::Handler, THandler>::value,
740 "Incompatible handlers");
741
742 using RetType = MessageInterfaceDispatchRetType<THandler>;
743 return static_cast<RetType>(msg.dispatch(handler));
744 }
745
746 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
747 static auto dispatchInternal(TId&& id, std::size_t offset, TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
748 decltype(handler.handle(msg))
749 {
750 static_cast<void>(id);
751 static_cast<void>(offset);
752 return handler.handle(msg);
753 }
754
755 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
756 static auto dispatchInternal(TId&& id, std::size_t offset, TMsgBase& msg, THandler& handler, DirectTag<TParams...>) ->
757 MessageInterfaceDispatchRetType<
758 typename std::decay<decltype(handler)>::type>
759 {
760 if (offset != 0U) {
761 using RetType = MessageInterfaceDispatchRetType<THandler>;
762 return static_cast<RetType>(handler.handle(msg));
763 }
764
765 return dispatchInternal<TAllMessages>(std::forward<TId>(id), msg, handler, DirectTag<>());
766 }
767
768 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
769 static auto dispatchInternal(TId&& id, std::size_t offset, TMsgBase& msg, THandler& handler, StrongBinSearchTag<TParams...>) ->
770 MessageInterfaceDispatchRetType<
771 typename std::decay<decltype(handler)>::type>
772 {
773 if (offset != 0U) {
774 using RetType = MessageInterfaceDispatchRetType<THandler>;
775 return static_cast<RetType>(handler.handle(msg));
776 }
777
778 return dispatchInternal<TAllMessages>(std::forward<TId>(id), msg, handler, StrongBinSearchTag<>());
779 }
780
781 template <typename TAllMessages, typename TId, typename TMsgBase, typename THandler, typename... TParams>
782 static auto dispatchInternal(TId&& id, std::size_t offset, TMsgBase& msg, THandler& handler, WeakBinSearchTag<TParams...>) ->
783 MessageInterfaceDispatchRetType<
784 typename std::decay<decltype(handler)>::type>
785 {
786 using MsgType = typename std::decay<decltype(msg)>::type;
787 using HandlerType = typename std::decay<decltype(handler)>::type;
788
789 return DispatchMsgBinSearchWeakPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
790 dispatch(std::forward<TId>(id), offset, msg, handler);
791 }
792};
793
794// ------------------------------------------------
795
796template <typename THandler>
797class PolymorphicTypeDirectDispatchMethod
798{
799public:
800 PolymorphicTypeDirectDispatchMethod(const PolymorphicTypeDirectDispatchMethod&) = delete;
801 PolymorphicTypeDirectDispatchMethod& operator=(const PolymorphicTypeDirectDispatchMethod&) = delete;
802
803 virtual void dispatch(THandler& handler) const
804 {
805 dispatchImpl(handler);
806 }
807
808protected:
809 PolymorphicTypeDirectDispatchMethod() = default;
810 ~PolymorphicTypeDirectDispatchMethod() = default;
811
812 virtual void dispatchImpl(THandler& handler) const = 0;
813};
814
815template <typename THandler, typename TMessage>
816class PolymorphicTypeDirectDispatchMethodImpl : public
817 PolymorphicTypeDirectDispatchMethod<THandler>
818{
819public:
820 PolymorphicTypeDirectDispatchMethodImpl() = default;
821 PolymorphicTypeDirectDispatchMethodImpl(const PolymorphicTypeDirectDispatchMethodImpl&) = delete;
822 PolymorphicTypeDirectDispatchMethodImpl& operator=(const PolymorphicTypeDirectDispatchMethodImpl&) = delete;
823
824protected:
825 virtual void dispatchImpl(THandler& handler) const
826#ifndef COMMS_COMPILER_GCC47
827 override final
828#endif
829 {
830 return handler.template handle<TMessage>();
831 }
832};
833
834template <typename TMsgIdType, typename THandler>
835class PolymorphicTypeBinSearchDispatchMethod
836{
837public:
838 PolymorphicTypeBinSearchDispatchMethod(const PolymorphicTypeBinSearchDispatchMethod&) = delete;
839 PolymorphicTypeBinSearchDispatchMethod& operator=(const PolymorphicTypeBinSearchDispatchMethod&) = delete;
840
841 virtual TMsgIdType getId() const
842 {
843 return getIdImpl();
844 }
845
846 virtual void dispatch(THandler& handler) const
847 {
848 return dispatchImpl(handler);
849 }
850
851protected:
852 PolymorphicTypeBinSearchDispatchMethod() = default;
853 ~PolymorphicTypeBinSearchDispatchMethod() = default;
854
855 virtual TMsgIdType getIdImpl() const = 0;
856 virtual void dispatchImpl(THandler& handler) const = 0;
857};
858
859template <typename TMsgIdType, typename THandler, typename TMessage>
860class PolymorphicTypeBinSearchDispatchMethodImpl : public
861 PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>
862{
863 using Base = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
864public:
865 PolymorphicTypeBinSearchDispatchMethodImpl() = default;
866 PolymorphicTypeBinSearchDispatchMethodImpl(const PolymorphicTypeBinSearchDispatchMethodImpl&) = delete;
867 PolymorphicTypeBinSearchDispatchMethodImpl& operator=(const PolymorphicTypeBinSearchDispatchMethodImpl&) = delete;
868
869 static TMsgIdType doGetId()
870 {
871 return dispatchMsgGetMsgId<TMessage>();
872 }
873
874protected:
875 virtual TMsgIdType getIdImpl() const
876#ifndef COMMS_COMPILER_GCC47
877 override final
878#endif
879 {
880 return doGetId();
881 }
882
883 virtual void dispatchImpl(THandler& handler) const
884#ifndef COMMS_COMPILER_GCC47
885 override final
886#endif
887 {
888 return handler.template handle<TMessage>();
889 }
890};
891
892template <typename THandler, std::size_t TSize>
893using PolymorphicTypeDirectDispatchMsgRegistry =
894 std::array<const PolymorphicTypeDirectDispatchMethod<THandler>*, TSize>;
895
896template <typename TMsgIdType, typename THandler, std::size_t TSize>
897using PolymorphicTypeBinSearchDispatchMsgRegistry =
898 std::array<const PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>*, TSize>;
899
900template <typename THandler>
901class PolymorphicTypeDirectDispatchRegistryFiller
902{
903public:
904 using DispatchMethod = PolymorphicTypeDirectDispatchMethod<THandler>;
905 PolymorphicTypeDirectDispatchRegistryFiller(const DispatchMethod** registry)
906 : m_registry(registry)
907 {
908 }
909
910 template <typename TMessage>
911 void operator()()
912 {
913 static_assert(comms::isMessageBase<TMessage>(), "Must be actual message");
914 static_assert(messageHasStaticNumId<TMessage>(), "Message must define static ID");
915 static const PolymorphicTypeDirectDispatchMethodImpl<THandler, TMessage> Method{};
916 m_registry[static_cast<std::size_t>(TMessage::doGetId())] = &Method;
917 }
918private:
919 const DispatchMethod** m_registry;
920};
921
922template <typename THandler, std::size_t TSize>
923PolymorphicTypeDirectDispatchRegistryFiller<THandler>
924polymorphicTypeDirectDispatchMakeRegistryFiller(
925 PolymorphicTypeDirectDispatchMsgRegistry<THandler, TSize>& registry)
926{
927 return PolymorphicTypeDirectDispatchRegistryFiller<THandler>(&registry[0]);
928}
929
930template <typename TRegistry, typename TAllMessages>
931class PolymorphicTypeDirectDispatchRegistryInitializer
932{
933public:
934 PolymorphicTypeDirectDispatchRegistryInitializer() = delete;
935 PolymorphicTypeDirectDispatchRegistryInitializer(const PolymorphicTypeDirectDispatchRegistryInitializer&) = delete;
936 explicit PolymorphicTypeDirectDispatchRegistryInitializer(TRegistry& registry)
937 {
938 std::fill(registry.begin(), registry.end(), nullptr);
939 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeDirectDispatchMakeRegistryFiller(registry));
940 }
941};
942
943template <typename TMsgIdType, typename THandler>
944class PolymorphicTypeBinSearchDispatchRegistryFiller
945{
946public:
947 using DispatchMethod = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
948 PolymorphicTypeBinSearchDispatchRegistryFiller(const DispatchMethod** registry)
949 : m_registry(registry)
950 {
951 }
952
953 template <typename TMessage>
954 void operator()()
955 {
956 // static_assert(comms::isMessageBase<TMessage>(), "Must be actual message");
957 // static_assert(messageHasStaticNumId<TMessage>(), "Message must define static ID");
958 static const PolymorphicTypeBinSearchDispatchMethodImpl<TMsgIdType, THandler, TMessage> Method{};
959 m_registry[m_idx] = &Method;
960 ++m_idx;
961 }
962
963private:
964 const DispatchMethod** m_registry;
965 std::size_t m_idx = 0U;
966};
967
968template <typename TMsgIdType, typename THandler, std::size_t TSize>
969PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>
970polymorphicTypeBinSearchDispatchMakeRegistryFiller(
971 PolymorphicTypeBinSearchDispatchMsgRegistry<TMsgIdType, THandler, TSize>& registry)
972{
973 return PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>(&registry[0]);
974}
975
976template <typename TRegistry, typename TAllMessages>
977class PolymorphicTypeBinSearchDispatchRegistryInitializer
978{
979public:
980 explicit PolymorphicTypeBinSearchDispatchRegistryInitializer(TRegistry& registry)
981 {
982 std::fill(registry.begin(), registry.end(), nullptr);
983 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeBinSearchDispatchMakeRegistryFiller(registry));
984 }
985};
986
987template <typename TAllMessages, typename THandler>
988class DispatchMsgTypeDirectPolymorphicHelper
989{
990public:
991 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
992 static_assert(FirstMsgType::hasMsgIdType(), "Message interface class must define its id type");
993 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
994 static bool dispatch(MsgIdParamType id, THandler& handler)
995 {
996 // Access initializer object to ensure it hasn't been erased by the optimizer
997 static_cast<void>(s_initializer);
998
999 auto regIdx = static_cast<std::size_t>(id);
1000 if ((s_registry.size() <= regIdx) ||
1001 (s_registry[regIdx] == nullptr)) {
1002 return false;
1003 }
1004
1005 s_registry[regIdx]->dispatch(handler);
1006 return true;
1007 }
1008
1009private:
1010 static const std::size_t RegistrySize =
1011 PolymorphicDirectDispatchRegSizeDetect<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
1012 using Registry = PolymorphicTypeDirectDispatchMsgRegistry<THandler, RegistrySize>;
1013 using Initializer = PolymorphicTypeDirectDispatchRegistryInitializer<Registry, TAllMessages>;
1014
1015 static Registry s_registry;
1016 static const Initializer s_initializer;
1017};
1018
1019template <typename TAllMessages, typename THandler>
1020typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Registry
1021DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_registry;
1022
1023template <typename TAllMessages, typename THandler>
1024const typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Initializer
1025DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_initializer(s_registry);
1026
1027template <typename TAllMessages, typename THandler>
1028class DispatchMsgTypeBinSearchPolymorphicHelperBase
1029{
1030protected:
1031 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
1032 static_assert(comms::isMessage<FirstMsgType>(),
1033 "The type in the tuple are expected to be proper messages");
1034 static_assert(FirstMsgType::hasMsgIdType(), "Message interface class must define its id type");
1035 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
1036
1037 static const std::size_t RegistrySize = std::tuple_size<TAllMessages>::value;
1038 using Registry = PolymorphicTypeBinSearchDispatchMsgRegistry<MsgIdParamType, THandler, RegistrySize>;
1039 using Initializer = PolymorphicTypeBinSearchDispatchRegistryInitializer<Registry, TAllMessages>;
1040
1041 static Registry s_registry;
1042 static Initializer s_initializer;
1043};
1044
1045template <typename TAllMessages, typename THandler>
1046typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Registry
1047DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_registry;
1048
1049template <typename TAllMessages, typename THandler>
1050typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Initializer
1051DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_initializer(s_registry);
1052
1053template <typename TAllMessages, typename THandler>
1054class DispatchMsgTypeBinSearchStrongPolymorphicHelper : public
1055 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1056{
1057 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1058 using Registry = typename Base::Registry;
1059public:
1060 using MsgIdParamType = typename Base::MsgIdParamType;
1061 static bool dispatch(MsgIdParamType id, THandler& handler)
1062 {
1063 // Access initializer object to ensure it hasn't been erased by the optimizer
1064 static_cast<void>(Base::s_initializer);
1065
1066 auto iter =
1067 std::lower_bound(
1068 Base::s_registry.begin(), Base::s_registry.end(), id,
1069 [](typename Registry::value_type method, MsgIdParamType idParam) -> bool
1070 {
1071 COMMS_ASSERT(method != nullptr);
1072 return method->getId() < idParam;
1073 });
1074
1075 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
1076 return false;
1077 }
1078
1079 (*iter)->dispatch(handler);
1080 return true;
1081 }
1082};
1083
1084template <typename TAllMessages, typename THandler>
1085class DispatchMsgTypeBinSearchWeakPolymorphicHelper : public
1086 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1087{
1088 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1089 using Registry = typename Base::Registry;
1090
1091public:
1092 using MsgIdParamType = typename Base::MsgIdParamType;
1093 static bool dispatch(MsgIdParamType id, std::size_t offset, THandler& handler)
1094 {
1095 // Access initializer object to ensure it hasn't been erased by the optimizer
1096 static_cast<void>(Base::s_initializer);
1097
1098 using IdType = typename std::decay<decltype(id)>::type;
1099 auto lowerIter =
1100 std::lower_bound(
1101 Base::s_registry.begin(), Base::s_registry.end(), id,
1102 [](typename Registry::value_type method, IdType idParam) -> bool
1103 {
1104 COMMS_ASSERT(method != nullptr);
1105 return static_cast<IdType>(method->getId()) < idParam;
1106 });
1107
1108 if ((lowerIter == Base::s_registry.end()) ||
1109 (static_cast<IdType>((*lowerIter)->getId()) != id)) {
1110 return false;
1111 }
1112
1113 auto upperIter =
1114 std::upper_bound(
1115 lowerIter, Base::s_registry.end(), id,
1116 [](IdType idParam, typename Registry::value_type method)
1117 {
1118 return idParam < static_cast<IdType>(method->getId());
1119 }
1120 );
1121
1122 COMMS_ASSERT(lowerIter < upperIter);
1123
1124 auto dist = static_cast<std::size_t>(upperIter - lowerIter);
1125 if (dist <= offset) {
1126 return false;
1127 }
1128
1129 auto actualIter = lowerIter + offset;
1130 (*actualIter)->dispatch(handler);
1131 return true;
1132 }
1133};
1134
1135template <typename...>
1136class DispatchMsgTypePolymorphicHelper
1137{
1138 template <typename... TParams>
1139 using EmptyTag = comms::details::tag::Tag1<>;
1140
1141 template <typename... TParams>
1142 using DirectTag = comms::details::tag::Tag2<>;
1143
1144 template <typename... TParams>
1145 using StrongBinSearchTag = comms::details::tag::Tag3<>;
1146
1147 template <typename... TParams>
1148 using WeakBinSearchTag = comms::details::tag::Tag4<>;
1149
1150 template <typename TAllMessages, typename...>
1151 using DirectStrongTag =
1152 typename comms::util::LazyShallowConditional<
1153 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
1154 >::template Type<
1155 DirectTag,
1156 StrongBinSearchTag
1157 >;
1158
1159 template <typename TAllMessages, typename...>
1160 using DirectStrongWeakTag =
1161 typename comms::util::LazyShallowConditional<
1162 allMessagesAreStrongSorted<TAllMessages>()
1163 >::template Type<
1164 DirectStrongTag,
1165 WeakBinSearchTag,
1166 TAllMessages
1167 >;
1168
1169 template <typename TAllMessages, typename...>
1170 using Tag =
1171 typename comms::util::LazyShallowConditional<
1172 std::tuple_size<TAllMessages>::value == 0U
1173 >::template Type<
1174 EmptyTag,
1175 DirectStrongWeakTag,
1176 TAllMessages
1177 >;
1178
1179public:
1180 template <typename TAllMessages, typename TId, typename THandler>
1181 static bool dispatch(TId&& id, THandler& handler)
1182 {
1183 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1184 "Message types must be sorted by their ID");
1185
1186 return dispatchInternal<TAllMessages>(std::forward<TId>(id), handler, Tag<TAllMessages>());
1187 }
1188
1189 template <typename TAllMessages, typename TId, typename THandler>
1190 static bool dispatch(TId&& id, std::size_t offset, THandler& handler)
1191 {
1192 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1193 "Message types must be sorted by their ID");
1194
1195 return dispatchInternal<TAllMessages>(std::forward<TId>(id), offset, handler, Tag<TAllMessages>());
1196 }
1197
1198private:
1199
1200 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1201 static bool dispatchInternal(TId&& id, THandler& handler, EmptyTag<TParams...>)
1202 {
1203 static_cast<void>(id);
1204 static_cast<void>(handler);
1205 return false;
1206 }
1207
1208 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1209 static bool dispatchInternal(TId&& id, std::size_t offset, THandler& handler, EmptyTag<TParams...>)
1210 {
1211 static_cast<void>(id);
1212 static_cast<void>(handler);
1213 static_cast<void>(offset);
1214 return false;
1215 }
1216
1217 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1218 static bool dispatchInternal(TId&& id, THandler& handler, DirectTag<TParams...>)
1219 {
1220 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
1221 static_assert(comms::isMessage<FirstMsgType>(),
1222 "The type in the tuple are expected to be proper messages");
1223 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
1224 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
1225 using HandlerType = typename std::decay<decltype(handler)>::type;
1226 return DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, HandlerType>::
1227 dispatch(static_cast<MsgIdParamType>(id), handler);
1228 }
1229
1230 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1231 static bool dispatchInternal(TId&& id, std::size_t offset, THandler& handler, DirectTag<TParams...>)
1232 {
1233 if (offset != 0U) {
1234 return false;
1235 }
1236
1237 return dispatchInternal<TAllMessages>(std::forward<TId>(id), handler, DirectTag<>());
1238 }
1239
1240 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1241 static bool dispatchInternal(TId&& id, THandler& handler, StrongBinSearchTag<TParams...>)
1242 {
1243 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
1244 static_assert(comms::isMessage<FirstMsgType>(),
1245 "The type in the tuple are expected to be proper messages");
1246 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
1247 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
1248 using HandlerType = typename std::decay<decltype(handler)>::type;
1249 return DispatchMsgTypeBinSearchStrongPolymorphicHelper<TAllMessages, HandlerType>::
1250 dispatch(static_cast<MsgIdParamType>(id), handler);
1251 }
1252
1253 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1254 static bool dispatchInternal(TId&& id, std::size_t offset, THandler& handler, StrongBinSearchTag<TParams...>)
1255 {
1256 if (offset != 0U) {
1257 return false;
1258 }
1259
1260 return dispatchInternal<TAllMessages>(std::forward<TId>(id), handler, StrongBinSearchTag<>());
1261 }
1262
1263 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1264 static bool dispatchInternal(TId&& id, THandler& handler, WeakBinSearchTag<TParams...>)
1265 {
1266 return dispatchInternal<TAllMessages>(std::forward<TId>(id), 0U, handler, WeakBinSearchTag<>());
1267 }
1268
1269 template <typename TAllMessages, typename TId, typename THandler, typename... TParams>
1270 static bool dispatchInternal(TId&& id, std::size_t offset, THandler& handler, WeakBinSearchTag<TParams...>)
1271 {
1272 using FirstMsgType = typename std::tuple_element<0, TAllMessages>::type;
1273 static_assert(comms::isMessage<FirstMsgType>(),
1274 "The type in the tuple are expected to be proper messages");
1275 static_assert(FirstMsgType::hasMsgIdType(), "The messages must define their ID type");
1276 using MsgIdParamType = typename FirstMsgType::MsgIdParamType;
1277 using HandlerType = typename std::decay<decltype(handler)>::type;
1278 return DispatchMsgTypeBinSearchWeakPolymorphicHelper<TAllMessages, HandlerType>::
1279 dispatch(static_cast<MsgIdParamType>(id), offset, handler);
1280 }
1281};
1282
1283} // namespace details
1284
1285} // namespace comms
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
Contains various compiler related definitions.
Provides common base class for the custom messages with default implementation.
Contains definition of Message object interface and various base classes for custom messages.
Contains various tuple type manipulation classes and functions.
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition options.h:1500
comms::option::def::MsgIdType< T > MsgIdType
Same as comms::option::def::MsgIdType.
Definition options.h:1486
Main namespace for all classes / functions of COMMS library.
Replacement to some types from standard type_traits.