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