20#include "comms/details/DispatchMsgIdRetrieveHelper.h"
21#include "comms/details/tag.h"
31template <
typename TMsgBase,
typename THandler>
32class PolymorphicDirectDispatchMethod
35 PolymorphicDirectDispatchMethod(
const PolymorphicDirectDispatchMethod&) =
delete;
36 PolymorphicDirectDispatchMethod& operator=(
const PolymorphicDirectDispatchMethod&) =
delete;
38 virtual auto dispatch(TMsgBase& msg, THandler& handler)
const ->
39 MessageInterfaceDispatchRetType<THandler>
41 return dispatchImpl(msg, handler);
45 PolymorphicDirectDispatchMethod() =
default;
46 ~PolymorphicDirectDispatchMethod() =
default;
48 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
49 MessageInterfaceDispatchRetType<THandler> = 0;
52template <
typename TMsgBase,
typename THandler,
typename TMessage>
53class PolymorphicDirectDispatchMethodImpl :
public
54 PolymorphicDirectDispatchMethod<TMsgBase, THandler>
57 PolymorphicDirectDispatchMethodImpl() =
default;
58 PolymorphicDirectDispatchMethodImpl(
const PolymorphicDirectDispatchMethodImpl&) =
delete;
59 PolymorphicDirectDispatchMethodImpl& operator=(
const PolymorphicDirectDispatchMethodImpl&) =
delete;
62 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
63 MessageInterfaceDispatchRetType<THandler>
64#ifndef COMMS_COMPILER_GCC47
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);
74template <
typename TMsgBase,
typename THandler>
75class PolymorphicBinSearchDispatchMethod
78 PolymorphicBinSearchDispatchMethod(
const PolymorphicBinSearchDispatchMethod&) =
delete;
79 PolymorphicBinSearchDispatchMethod& operator=(
const PolymorphicBinSearchDispatchMethod&) =
delete;
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;
85 virtual MsgIdParamType getId()
const
90 virtual auto dispatch(TMsgBase& msg, THandler& handler)
const ->
91 MessageInterfaceDispatchRetType<THandler>
93 return dispatchImpl(msg, handler);
97 PolymorphicBinSearchDispatchMethod() =
default;
98 ~PolymorphicBinSearchDispatchMethod() =
default;
100 virtual MsgIdParamType getIdImpl()
const = 0;
101 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
102 MessageInterfaceDispatchRetType<THandler> = 0;
105template <
typename TMsgBase,
typename THandler,
typename TMessage>
106class PolymorphicBinSearchDispatchMethodImpl :
public
107 PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>
109 using Base = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
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;
115 PolymorphicBinSearchDispatchMethodImpl() =
default;
116 PolymorphicBinSearchDispatchMethodImpl(
const PolymorphicBinSearchDispatchMethodImpl&) =
delete;
117 PolymorphicBinSearchDispatchMethodImpl& operator=(
const PolymorphicBinSearchDispatchMethodImpl&) =
delete;
120 static MsgIdParamType doGetId()
122 return dispatchMsgGetMsgId<TMessage>();
127 virtual MsgIdParamType getIdImpl() const
128#ifndef COMMS_COMPILER_GCC47
135 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
136 MessageInterfaceDispatchRetType<THandler>
137#ifndef COMMS_COMPILER_GCC47
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);
147template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
148using PolymorphicDirectDispatchMsgRegistry =
149 std::array<const PolymorphicDirectDispatchMethod<TMsgBase, THandler>*, TSize>;
151template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
152using PolymorphicBinSearchDispatchMsgRegistry =
153 std::array<const PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>*, TSize>;
156template <
typename TMsgBase,
typename THandler>
157class PolymorphicDirectDispatchRegistryFiller
160 using DispatchMethod = PolymorphicDirectDispatchMethod<TMsgBase, THandler>;
161 PolymorphicDirectDispatchRegistryFiller(
const DispatchMethod** registry)
162 : m_registry(registry)
166 template <
typename TMessage>
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;
175 const DispatchMethod** m_registry;
178template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
179PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>
180polymorphicDirectDispatchMakeRegistryFiller(
181 PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
183 return PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>(®istry[0]);
186template <
typename TRegistry,
typename TAllMessages>
187class PolymorphicDirectDispatchRegistryInitializer
190 PolymorphicDirectDispatchRegistryInitializer() =
delete;
191 PolymorphicDirectDispatchRegistryInitializer(
const PolymorphicDirectDispatchRegistryInitializer&) =
delete;
192 explicit PolymorphicDirectDispatchRegistryInitializer(TRegistry& registry)
194 std::fill(registry.begin(), registry.end(),
nullptr);
195 comms::util::tupleForEachType<TAllMessages>(polymorphicDirectDispatchMakeRegistryFiller(registry));
199template <
typename TMsgBase,
typename THandler>
200class PolymorphicBinSearchDispatchRegistryFiller
203 using DispatchMethod = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
204 PolymorphicBinSearchDispatchRegistryFiller(
const DispatchMethod** registry)
205 : m_registry(registry)
209 template <
typename TMessage>
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;
220 const DispatchMethod** m_registry;
221 std::size_t m_idx = 0U;
224template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
225PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>
226polymorphicBinSearchDispatchMakeRegistryFiller(
227 PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
229 return PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>(®istry[0]);
232template <
typename TRegistry,
typename TAllMessages>
233class PolymorphicBinSearchDispatchRegistryInitializer
236 explicit PolymorphicBinSearchDispatchRegistryInitializer(TRegistry& registry)
238 std::fill(registry.begin(), registry.end(),
nullptr);
239 comms::util::tupleForEachType<TAllMessages>(polymorphicBinSearchDispatchMakeRegistryFiller(registry));
243template <
typename TAllMessages, std::
size_t TMaxSize>
244class PolymorphicDirectDispatchRegSizeDetect
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();
252 static const std::size_t Value =
static_cast<std::size_t
>(MsgId) + 1U;
255template <
typename TAllMessages>
256class PolymorphicDirectDispatchRegSizeDetect<TAllMessages, 0U>
259 static const std::size_t Value = 0;
262template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
263class DispatchMsgDirectPolymorphicHelper
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>
273 static_cast<void>(s_initializer);
276 MessageInterfaceDispatchRetType<
277 typename std::decay<
decltype(handler)>::type>;
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));
285 return static_cast<RetType
>(s_registry[regIdx]->dispatch(msg, handler));
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>;
294 static Registry s_registry;
295 static const Initializer s_initializer;
298template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
299typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Registry
300DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_registry;
302template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
303const typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Initializer
304DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
306template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
307class DispatchMsgBinSearchPolymorphicHelperBase
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>;
314 static Registry s_registry;
315 static Initializer s_initializer;
318template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
319typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Registry
320DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_registry;
322template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
323typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Initializer
324DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
326template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
327class DispatchMsgBinSearchStrongPolymorphicHelper :
public
328 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
330 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
331 using Registry =
typename Base::Registry;
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>
340 static_cast<void>(Base::s_initializer);
343 MessageInterfaceDispatchRetType<
344 typename std::decay<
decltype(handler)>::type>;
348 Base::s_registry.begin(), Base::s_registry.end(),
id,
349 [](
typename Registry::value_type method, MsgIdParamType idParam) ->
bool
352 return method->getId() < idParam;
355 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
356 return static_cast<RetType
>(handler.handle(msg));
359 return static_cast<RetType
>((*iter)->dispatch(msg, handler));
363template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
364class DispatchMsgBinSearchWeakPolymorphicHelper :
public
365 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
367 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
368 using Registry =
typename Base::Registry;
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>
376 static_cast<void>(Base::s_initializer);
379 MessageInterfaceDispatchRetType<
380 typename std::decay<
decltype(handler)>::type>;
382 using IdType =
typename std::decay<
decltype(id)>::type;
386 Base::s_registry.begin(), Base::s_registry.end(),
id,
387 [](
typename Registry::value_type method, IdType idParam) ->
bool
390 return static_cast<IdType
>(method->getId()) < idParam;
393 if ((lowerIter == Base::s_registry.end()) ||
394 (
static_cast<IdType
>((*lowerIter)->getId()) != id)) {
395 return static_cast<RetType
>(handler.handle(msg));
400 lowerIter, Base::s_registry.end(),
id,
401 [](IdType idParam,
typename Registry::value_type method)
403 return idParam < static_cast<IdType>(method->getId());
409 auto dist =
static_cast<std::size_t
>(upperIter - lowerIter);
410 if (dist <= offset) {
411 return static_cast<RetType
>(handler.handle(msg));
414 auto actualIter = lowerIter + offset;
415 return static_cast<RetType
>((*actualIter)->dispatch(msg, handler));
419template <
typename TElem,
bool TIsMessage>
420struct DispatchMsgPolymorphicLastIdRetriever;
422template <
typename TElem>
423struct DispatchMsgPolymorphicLastIdRetriever<TElem, true>
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());
430template <
typename TElem>
431struct DispatchMsgPolymorphicLastIdRetriever<TElem, false>
433 static const std::size_t Value = std::numeric_limits<std::size_t>::max();
436template <
typename TAllMessages, std::
size_t TCount>
437class DispatchMsgPolymorphicIsDirectSuitable
440 typename std::tuple_element<
441 std::tuple_size<TAllMessages>::value - 1,
446 static const std::size_t MaxId =
447 DispatchMsgPolymorphicLastIdRetriever<LastMsg, comms::isMessageBase<LastMsg>()>::Value;
449 static const std::size_t MaxAllowedId = (TCount * 11) / 10;
452 static const bool Value =
453 (MaxId <= (TCount + 10U)) || (MaxId <= MaxAllowedId);
456template <
typename TAllMessages>
457class DispatchMsgPolymorphicIsDirectSuitable<TAllMessages, 0U>
460 static const bool Value =
true;
463template <
typename TAllMessages>
464static constexpr bool dispatchMsgPolymorphicIsDirectSuitable()
467 allMessagesHaveStaticNumId<TAllMessages>() &&
468 DispatchMsgPolymorphicIsDirectSuitable<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
471template <
typename...>
472struct DispatchMsgPolymorphicCompatibleHandlerDetector
474 template <
typename TMsg,
typename THandler>
475 using Type = std::is_base_of<typename TMsg::Handler, THandler>;
478template <
typename TMsg,
typename THandler>
479using DispatchMsgPolymorphicCompatibleHandlerDetectBoolType =
480 typename comms::util::LazyDeepConditional<
483 DispatchMsgPolymorphicCompatibleHandlerDetector,
484 comms::util::FalseType,
489template <
typename TMsg,
typename THandler>
490constexpr bool dispatchMsgPolymorphicIsCompatibleHandler()
492 return DispatchMsgPolymorphicCompatibleHandlerDetectBoolType<TMsg, THandler>::value;
495template <
typename ...>
496class DispatchMsgPolymorphicHelper
498 template <
typename... TParams>
499 using EmptyTag = comms::details::tag::Tag1<>;
501 template <
typename... TParams>
502 using DispatchInterfaceTag = comms::details::tag::Tag2<>;
504 template <
typename... TParams>
505 using DirectTag = comms::details::tag::Tag3<>;
507 template <
typename... TParams>
508 using StrongBinSearchTag = comms::details::tag::Tag4<>;
510 template <
typename... TParams>
511 using WeakBinSearchTag = comms::details::tag::Tag5<>;
513 template <
typename... TParams>
514 using IdInterfaceTag = comms::details::tag::Tag6<>;
516 template <
typename... TParams>
517 using NoIdInterfaceTag = comms::details::tag::Tag7<>;
519 template <
typename TAllMessages,
typename...>
520 using DirectStrongTag =
521 typename comms::util::LazyShallowConditional<
522 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
528 template <
typename TAllMessages,
typename...>
529 using DirectStrongWeakTag =
530 typename comms::util::LazyShallowConditional<
531 allMessagesAreStrongSorted<TAllMessages>()
539 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename...>
541 typename comms::util::LazyShallowConditional<
542 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
544 DispatchInterfaceTag,
549 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename...>
551 typename comms::util::LazyShallowConditional<
552 comms::isMessageBase<TMsgBase>()
556 TAllMessages, TMsgBase, THandler
559 template <
typename TMsgBase,
typename...>
560 using InterfaceDispatchTag =
561 typename comms::util::LazyShallowConditional<
568 template <
typename TMsgBase,
typename THandler,
typename...>
569 using PolymorphicCheckDispatchTag =
570 typename comms::util::LazyShallowConditional<
571 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
574 InterfaceDispatchTag,
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>
585 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
586 "Message types must be sorted by their ID");
588 static_assert(comms::isMessage<TMsgBase>(),
589 "TMsgBase is expected to be message interface class");
591 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
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>()
600 PolymorphicCheckDispatchTag,
604 return dispatchInternal<TAllMessages>(msg, handler, IdRetrieveTag());
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>
612 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
613 "Message types must be sorted by their ID");
615 static_assert(comms::isMessage<TMsgBase>(),
616 "TMsgBase is expected to be message interface class");
618 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
620 using MsgType =
typename std::decay<
decltype(msg)>::type;
621 using HandlerType =
typename std::decay<
decltype(handler)>::type;
623 dispatchInternal<TAllMessages>(
624 static_cast<typename MsgType::MsgIdParamType
>(
id),
627 AdjustedTag<TAllMessages, MsgType, HandlerType>());
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>
635 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
636 "Message types must be sorted by their ID");
638 static_assert(comms::isMessage<TMsgBase>(),
639 "TMsgBase is expected to be message interface class");
641 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
643 using MsgType =
typename std::decay<
decltype(msg)>::type;
644 using HandlerType =
typename std::decay<
decltype(handler)>::type;
646 dispatchInternal<TAllMessages>(
647 static_cast<typename MsgType::MsgIdParamType
>(
id),
651 AdjustedTag<TAllMessages, MsgType, HandlerType>());
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))
659 return handler.handle(msg);
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>
667 typename TMsgBase::MsgIdParamType
id = msg.getId();
668 return dispatch<TAllMessages>(
id, msg, handler);
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>
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");
680 using RetType = MessageInterfaceDispatchRetType<THandler>;
681 return static_cast<RetType
>(msg.dispatch(handler));
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))
688 static_cast<void>(id);
689 return handler.handle(msg);
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>
697 static_cast<void>(id);
698 return dispatchInternal<TAllMessages>(msg, handler, NoIdInterfaceTag<>());
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>
706 using MsgType =
typename std::decay<
decltype(msg)>::type;
707 using HandlerType =
typename std::decay<
decltype(handler)>::type;
709 return DispatchMsgDirectPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
710 dispatch(std::forward<TId>(
id), msg, handler);
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>
718 using MsgType =
typename std::decay<
decltype(msg)>::type;
719 using HandlerType =
typename std::decay<
decltype(handler)>::type;
721 return DispatchMsgBinSearchStrongPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
722 dispatch(std::forward<TId>(
id), msg, handler);
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>
730 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), 0U, msg, handler, WeakBinSearchTag<>());
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>
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");
743 using RetType = MessageInterfaceDispatchRetType<THandler>;
744 return static_cast<RetType
>(msg.dispatch(handler));
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))
751 static_cast<void>(id);
752 static_cast<void>(offset);
753 return handler.handle(msg);
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>
762 using RetType = MessageInterfaceDispatchRetType<THandler>;
763 return static_cast<RetType
>(handler.handle(msg));
766 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), msg, handler, DirectTag<>());
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>
775 using RetType = MessageInterfaceDispatchRetType<THandler>;
776 return static_cast<RetType
>(handler.handle(msg));
779 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), msg, handler, StrongBinSearchTag<>());
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>
787 using MsgType =
typename std::decay<
decltype(msg)>::type;
788 using HandlerType =
typename std::decay<
decltype(handler)>::type;
790 return DispatchMsgBinSearchWeakPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
791 dispatch(std::forward<TId>(
id), offset, msg, handler);
797template <
typename THandler>
798class PolymorphicTypeDirectDispatchMethod
801 PolymorphicTypeDirectDispatchMethod(
const PolymorphicTypeDirectDispatchMethod&) =
delete;
802 PolymorphicTypeDirectDispatchMethod& operator=(
const PolymorphicTypeDirectDispatchMethod&) =
delete;
804 virtual void dispatch(THandler& handler)
const
806 dispatchImpl(handler);
810 PolymorphicTypeDirectDispatchMethod() =
default;
811 ~PolymorphicTypeDirectDispatchMethod() =
default;
813 virtual void dispatchImpl(THandler& handler)
const = 0;
816template <
typename THandler,
typename TMessage>
817class PolymorphicTypeDirectDispatchMethodImpl :
public
818 PolymorphicTypeDirectDispatchMethod<THandler>
821 PolymorphicTypeDirectDispatchMethodImpl() =
default;
822 PolymorphicTypeDirectDispatchMethodImpl(
const PolymorphicTypeDirectDispatchMethodImpl&) =
delete;
823 PolymorphicTypeDirectDispatchMethodImpl& operator=(
const PolymorphicTypeDirectDispatchMethodImpl&) =
delete;
826 virtual void dispatchImpl(THandler& handler)
const
827#ifndef COMMS_COMPILER_GCC47
831 return handler.template handle<TMessage>();
835template <
typename TMsgIdType,
typename THandler>
836class PolymorphicTypeBinSearchDispatchMethod
839 PolymorphicTypeBinSearchDispatchMethod(
const PolymorphicTypeBinSearchDispatchMethod&) =
delete;
840 PolymorphicTypeBinSearchDispatchMethod& operator=(
const PolymorphicTypeBinSearchDispatchMethod&) =
delete;
842 virtual TMsgIdType getId()
const
847 virtual void dispatch(THandler& handler)
const
849 return dispatchImpl(handler);
853 PolymorphicTypeBinSearchDispatchMethod() =
default;
854 ~PolymorphicTypeBinSearchDispatchMethod() =
default;
856 virtual TMsgIdType getIdImpl()
const = 0;
857 virtual void dispatchImpl(THandler& handler)
const = 0;
860template <
typename TMsgIdType,
typename THandler,
typename TMessage>
861class PolymorphicTypeBinSearchDispatchMethodImpl :
public
862 PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>
864 using Base = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
866 PolymorphicTypeBinSearchDispatchMethodImpl() =
default;
867 PolymorphicTypeBinSearchDispatchMethodImpl(
const PolymorphicTypeBinSearchDispatchMethodImpl&) =
delete;
868 PolymorphicTypeBinSearchDispatchMethodImpl& operator=(
const PolymorphicTypeBinSearchDispatchMethodImpl&) =
delete;
870 static TMsgIdType doGetId()
872 return dispatchMsgGetMsgId<TMessage>();
876 virtual TMsgIdType getIdImpl() const
877#ifndef COMMS_COMPILER_GCC47
884 virtual void dispatchImpl(THandler& handler)
const
885#ifndef COMMS_COMPILER_GCC47
889 return handler.template handle<TMessage>();
893template <
typename THandler, std::
size_t TSize>
894using PolymorphicTypeDirectDispatchMsgRegistry =
895 std::array<const PolymorphicTypeDirectDispatchMethod<THandler>*, TSize>;
897template <
typename TMsgIdType,
typename THandler, std::
size_t TSize>
898using PolymorphicTypeBinSearchDispatchMsgRegistry =
899 std::array<const PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>*, TSize>;
901template <
typename THandler>
902class PolymorphicTypeDirectDispatchRegistryFiller
905 using DispatchMethod = PolymorphicTypeDirectDispatchMethod<THandler>;
906 PolymorphicTypeDirectDispatchRegistryFiller(
const DispatchMethod** registry)
907 : m_registry(registry)
911 template <
typename TMessage>
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;
920 const DispatchMethod** m_registry;
923template <
typename THandler, std::
size_t TSize>
924PolymorphicTypeDirectDispatchRegistryFiller<THandler>
925polymorphicTypeDirectDispatchMakeRegistryFiller(
926 PolymorphicTypeDirectDispatchMsgRegistry<THandler, TSize>& registry)
928 return PolymorphicTypeDirectDispatchRegistryFiller<THandler>(®istry[0]);
931template <
typename TRegistry,
typename TAllMessages>
932class PolymorphicTypeDirectDispatchRegistryInitializer
935 PolymorphicTypeDirectDispatchRegistryInitializer() =
delete;
936 PolymorphicTypeDirectDispatchRegistryInitializer(
const PolymorphicTypeDirectDispatchRegistryInitializer&) =
delete;
937 explicit PolymorphicTypeDirectDispatchRegistryInitializer(TRegistry& registry)
939 std::fill(registry.begin(), registry.end(),
nullptr);
940 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeDirectDispatchMakeRegistryFiller(registry));
944template <
typename TMsgIdType,
typename THandler>
945class PolymorphicTypeBinSearchDispatchRegistryFiller
948 using DispatchMethod = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
949 PolymorphicTypeBinSearchDispatchRegistryFiller(
const DispatchMethod** registry)
950 : m_registry(registry)
954 template <
typename TMessage>
959 static const PolymorphicTypeBinSearchDispatchMethodImpl<TMsgIdType, THandler, TMessage> Method{};
960 m_registry[m_idx] = &Method;
965 const DispatchMethod** m_registry;
966 std::size_t m_idx = 0U;
969template <
typename TMsgIdType,
typename THandler, std::
size_t TSize>
970PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>
971polymorphicTypeBinSearchDispatchMakeRegistryFiller(
972 PolymorphicTypeBinSearchDispatchMsgRegistry<TMsgIdType, THandler, TSize>& registry)
974 return PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>(®istry[0]);
977template <
typename TRegistry,
typename TAllMessages>
978class PolymorphicTypeBinSearchDispatchRegistryInitializer
981 explicit PolymorphicTypeBinSearchDispatchRegistryInitializer(TRegistry& registry)
983 std::fill(registry.begin(), registry.end(),
nullptr);
984 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeBinSearchDispatchMakeRegistryFiller(registry));
988template <
typename TAllMessages,
typename THandler>
989class DispatchMsgTypeDirectPolymorphicHelper
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)
998 static_cast<void>(s_initializer);
1000 auto regIdx =
static_cast<std::size_t
>(id);
1001 if ((s_registry.size() <= regIdx) ||
1002 (s_registry[regIdx] ==
nullptr)) {
1006 s_registry[regIdx]->dispatch(handler);
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>;
1016 static Registry s_registry;
1017 static const Initializer s_initializer;
1020template <
typename TAllMessages,
typename THandler>
1021typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Registry
1022DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_registry;
1024template <
typename TAllMessages,
typename THandler>
1025const typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Initializer
1026DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_initializer(s_registry);
1028template <
typename TAllMessages,
typename THandler>
1029class DispatchMsgTypeBinSearchPolymorphicHelperBase
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;
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>;
1042 static Registry s_registry;
1043 static Initializer s_initializer;
1046template <
typename TAllMessages,
typename THandler>
1047typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Registry
1048DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_registry;
1050template <
typename TAllMessages,
typename THandler>
1051typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Initializer
1052DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_initializer(s_registry);
1054template <
typename TAllMessages,
typename THandler>
1055class DispatchMsgTypeBinSearchStrongPolymorphicHelper :
public
1056 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1058 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1059 using Registry =
typename Base::Registry;
1061 using MsgIdParamType =
typename Base::MsgIdParamType;
1062 static bool dispatch(MsgIdParamType
id, THandler& handler)
1065 static_cast<void>(Base::s_initializer);
1069 Base::s_registry.begin(), Base::s_registry.end(),
id,
1070 [](
typename Registry::value_type method, MsgIdParamType idParam) ->
bool
1073 return method->getId() < idParam;
1076 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
1080 (*iter)->dispatch(handler);
1085template <
typename TAllMessages,
typename THandler>
1086class DispatchMsgTypeBinSearchWeakPolymorphicHelper :
public
1087 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1089 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1090 using Registry =
typename Base::Registry;
1093 using MsgIdParamType =
typename Base::MsgIdParamType;
1094 static bool dispatch(MsgIdParamType
id, std::size_t offset, THandler& handler)
1097 static_cast<void>(Base::s_initializer);
1099 using IdType =
typename std::decay<
decltype(id)>::type;
1102 Base::s_registry.begin(), Base::s_registry.end(),
id,
1103 [](
typename Registry::value_type method, IdType idParam) ->
bool
1106 return static_cast<IdType
>(method->getId()) < idParam;
1109 if ((lowerIter == Base::s_registry.end()) ||
1110 (
static_cast<IdType
>((*lowerIter)->getId()) != id)) {
1116 lowerIter, Base::s_registry.end(),
id,
1117 [](IdType idParam,
typename Registry::value_type method)
1119 return idParam < static_cast<IdType>(method->getId());
1125 auto dist =
static_cast<std::size_t
>(upperIter - lowerIter);
1126 if (dist <= offset) {
1130 auto actualIter = lowerIter + offset;
1131 (*actualIter)->dispatch(handler);
1136template <
typename...>
1137class DispatchMsgTypePolymorphicHelper
1139 template <
typename... TParams>
1140 using EmptyTag = comms::details::tag::Tag1<>;
1142 template <
typename... TParams>
1143 using DirectTag = comms::details::tag::Tag2<>;
1145 template <
typename... TParams>
1146 using StrongBinSearchTag = comms::details::tag::Tag3<>;
1148 template <
typename... TParams>
1149 using WeakBinSearchTag = comms::details::tag::Tag4<>;
1151 template <
typename TAllMessages,
typename...>
1152 using DirectStrongTag =
1153 typename comms::util::LazyShallowConditional<
1154 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
1160 template <
typename TAllMessages,
typename...>
1161 using DirectStrongWeakTag =
1162 typename comms::util::LazyShallowConditional<
1163 allMessagesAreStrongSorted<TAllMessages>()
1171 template <
typename TAllMessages,
typename...>
1173 typename comms::util::LazyShallowConditional<
1174 std::tuple_size<TAllMessages>::value == 0U
1177 DirectStrongWeakTag,
1182 template <
typename TAllMessages,
typename TId,
typename THandler>
1183 static bool dispatch(TId&&
id, THandler& handler)
1185 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1186 "Message types must be sorted by their ID");
1188 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, Tag<TAllMessages>());
1191 template <
typename TAllMessages,
typename TId,
typename THandler>
1192 static bool dispatch(TId&&
id, std::size_t offset, THandler& handler)
1194 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1195 "Message types must be sorted by their ID");
1197 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), offset, handler, Tag<TAllMessages>());
1202 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1203 static bool dispatchInternal(TId&&
id, THandler& handler, EmptyTag<TParams...>)
1205 static_cast<void>(id);
1206 static_cast<void>(handler);
1210 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1211 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, EmptyTag<TParams...>)
1213 static_cast<void>(id);
1214 static_cast<void>(handler);
1215 static_cast<void>(offset);
1219 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1220 static bool dispatchInternal(TId&&
id, THandler& handler, DirectTag<TParams...>)
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);
1232 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1233 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, DirectTag<TParams...>)
1239 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, DirectTag<>());
1242 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1243 static bool dispatchInternal(TId&&
id, THandler& handler, StrongBinSearchTag<TParams...>)
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);
1255 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1256 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, StrongBinSearchTag<TParams...>)
1262 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, StrongBinSearchTag<>());
1265 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1266 static bool dispatchInternal(TId&&
id, THandler& handler, WeakBinSearchTag<TParams...>)
1268 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), 0U, handler, WeakBinSearchTag<>());
1271 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1272 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, WeakBinSearchTag<TParams...>)
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);
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.