13#include "comms/details/DispatchMsgIdRetrieveHelper.h"
14#include "comms/details/tag.h"
32template <
typename TMsgBase,
typename THandler>
33class PolymorphicDirectDispatchMethod
36 PolymorphicDirectDispatchMethod(
const PolymorphicDirectDispatchMethod&) =
delete;
37 PolymorphicDirectDispatchMethod& operator=(
const PolymorphicDirectDispatchMethod&) =
delete;
39 virtual auto dispatch(TMsgBase& msg, THandler& handler)
const ->
40 MessageInterfaceDispatchRetType<THandler>
42 return dispatchImpl(msg, handler);
46 PolymorphicDirectDispatchMethod() =
default;
47 ~PolymorphicDirectDispatchMethod() =
default;
49 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
50 MessageInterfaceDispatchRetType<THandler> = 0;
53template <
typename TMsgBase,
typename THandler,
typename TMessage>
54class PolymorphicDirectDispatchMethodImpl :
public
55 PolymorphicDirectDispatchMethod<TMsgBase, THandler>
58 PolymorphicDirectDispatchMethodImpl() =
default;
59 PolymorphicDirectDispatchMethodImpl(
const PolymorphicDirectDispatchMethodImpl&) =
delete;
60 PolymorphicDirectDispatchMethodImpl& operator=(
const PolymorphicDirectDispatchMethodImpl&) =
delete;
63 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
64 MessageInterfaceDispatchRetType<THandler>
65#ifndef COMMS_COMPILER_GCC47
69 static_assert(std::is_base_of<TMsgBase, TMessage>::value,
"TMessage must extend TMsgBase");
70 auto& castedMsg =
static_cast<TMessage&
>(msg);
71 return handler.handle(castedMsg);
75template <
typename TMsgBase,
typename THandler>
76class PolymorphicBinSearchDispatchMethod
79 PolymorphicBinSearchDispatchMethod(
const PolymorphicBinSearchDispatchMethod&) =
delete;
80 PolymorphicBinSearchDispatchMethod& operator=(
const PolymorphicBinSearchDispatchMethod&) =
delete;
82 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
83 using MsgIdParamType =
typename TMsgBase::MsgIdParamType;
84 using MsgIdType =
typename TMsgBase::MsgIdType;
86 virtual MsgIdParamType getId()
const
91 virtual auto dispatch(TMsgBase& msg, THandler& handler)
const ->
92 MessageInterfaceDispatchRetType<THandler>
94 return dispatchImpl(msg, handler);
98 PolymorphicBinSearchDispatchMethod() =
default;
99 ~PolymorphicBinSearchDispatchMethod() =
default;
101 virtual MsgIdParamType getIdImpl()
const = 0;
102 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
103 MessageInterfaceDispatchRetType<THandler> = 0;
106template <
typename TMsgBase,
typename THandler,
typename TMessage>
107class PolymorphicBinSearchDispatchMethodImpl :
public
108 PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>
110 using Base = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
112 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
113 using MsgIdParamType =
typename Base::MsgIdParamType;
114 using MsgIdType =
typename Base::MsgIdType;
116 PolymorphicBinSearchDispatchMethodImpl() =
default;
117 PolymorphicBinSearchDispatchMethodImpl(
const PolymorphicBinSearchDispatchMethodImpl&) =
delete;
118 PolymorphicBinSearchDispatchMethodImpl& operator=(
const PolymorphicBinSearchDispatchMethodImpl&) =
delete;
121 static MsgIdParamType doGetId()
123 return dispatchMsgGetMsgId<TMessage>();
128 virtual MsgIdParamType getIdImpl() const
129#ifndef COMMS_COMPILER_GCC47
136 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
137 MessageInterfaceDispatchRetType<THandler>
138#ifndef COMMS_COMPILER_GCC47
142 static_assert(std::is_base_of<TMsgBase, TMessage>::value,
"TMessage must extend TMsgBase");
143 auto& castedMsg =
static_cast<TMessage&
>(msg);
144 return handler.handle(castedMsg);
148template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
149using PolymorphicDirectDispatchMsgRegistry =
150 std::array<const PolymorphicDirectDispatchMethod<TMsgBase, THandler>*, TSize>;
152template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
153using PolymorphicBinSearchDispatchMsgRegistry =
154 std::array<const PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>*, TSize>;
157template <
typename TMsgBase,
typename THandler>
158class PolymorphicDirectDispatchRegistryFiller
161 using DispatchMethod = PolymorphicDirectDispatchMethod<TMsgBase, THandler>;
162 PolymorphicDirectDispatchRegistryFiller(
const DispatchMethod** registry)
163 : m_registry(registry)
167 template <
typename TMessage>
170 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
171 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
172 static const PolymorphicDirectDispatchMethodImpl<TMsgBase, THandler, TMessage> Method{};
173 m_registry[
static_cast<std::size_t
>(TMessage::doGetId())] = &Method;
176 const DispatchMethod** m_registry;
179template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
180PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>
181polymorphicDirectDispatchMakeRegistryFiller(
182 PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
184 return PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>(®istry[0]);
187template <
typename TRegistry,
typename TAllMessages>
188class PolymorphicDirectDispatchRegistryInitializer
191 PolymorphicDirectDispatchRegistryInitializer() =
delete;
192 PolymorphicDirectDispatchRegistryInitializer(
const PolymorphicDirectDispatchRegistryInitializer&) =
delete;
193 explicit PolymorphicDirectDispatchRegistryInitializer(TRegistry& registry)
195 std::fill(registry.begin(), registry.end(),
nullptr);
196 comms::util::tupleForEachType<TAllMessages>(polymorphicDirectDispatchMakeRegistryFiller(registry));
200template <
typename TMsgBase,
typename THandler>
201class PolymorphicBinSearchDispatchRegistryFiller
204 using DispatchMethod = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
205 PolymorphicBinSearchDispatchRegistryFiller(
const DispatchMethod** registry)
206 : m_registry(registry)
210 template <
typename TMessage>
213 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
214 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
215 static const PolymorphicBinSearchDispatchMethodImpl<TMsgBase, THandler, TMessage> Method{};
216 m_registry[m_idx] = &Method;
221 const DispatchMethod** m_registry;
222 std::size_t m_idx = 0U;
225template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
226PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>
227polymorphicBinSearchDispatchMakeRegistryFiller(
228 PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
230 return PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>(®istry[0]);
233template <
typename TRegistry,
typename TAllMessages>
234class PolymorphicBinSearchDispatchRegistryInitializer
237 explicit PolymorphicBinSearchDispatchRegistryInitializer(TRegistry& registry)
239 std::fill(registry.begin(), registry.end(),
nullptr);
240 comms::util::tupleForEachType<TAllMessages>(polymorphicBinSearchDispatchMakeRegistryFiller(registry));
244template <
typename TAllMessages, std::
size_t TMaxSize>
245class PolymorphicDirectDispatchRegSizeDetect
247 using MsgType =
typename std::tuple_element<TMaxSize - 1, TAllMessages>::type;
248 static_assert(comms::isMessageBase<MsgType>(),
"Must be actual message");
249 static_assert(messageHasStaticNumId<MsgType>(),
"Message must define static numeric ID");
250 static_assert(MsgType::hasMsgIdType(),
"Message interface class must define its id type");
251 static const typename MsgType::MsgIdParamType MsgId = MsgType::doGetId();
253 static const std::size_t Value =
static_cast<std::size_t
>(MsgId) + 1U;
256template <
typename TAllMessages>
257class PolymorphicDirectDispatchRegSizeDetect<TAllMessages, 0U>
260 static const std::size_t Value = 0;
263template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
264class DispatchMsgDirectPolymorphicHelper
267 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
268 using MsgIdParamType =
typename TMsgBase::MsgIdParamType;
269 static auto dispatch(MsgIdParamType
id, TMsgBase& msg, THandler& handler) ->
270 MessageInterfaceDispatchRetType<
271 typename std::decay<
decltype(handler)>::type>
274 static_cast<void>(s_initializer);
277 MessageInterfaceDispatchRetType<
278 typename std::decay<
decltype(handler)>::type>;
280 auto regIdx =
static_cast<std::size_t
>(id);
281 if ((s_registry.size() <= regIdx) ||
282 (s_registry[regIdx] ==
nullptr)) {
283 return static_cast<RetType
>(handler.handle(msg));
286 return static_cast<RetType
>(s_registry[regIdx]->dispatch(msg, handler));
290 static const std::size_t RegistrySize =
291 PolymorphicDirectDispatchRegSizeDetect<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
292 using Registry = PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, RegistrySize>;
293 using Initializer = PolymorphicDirectDispatchRegistryInitializer<Registry, TAllMessages>;
295 static Registry s_registry;
296 static const Initializer s_initializer;
299template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
300typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Registry
301DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_registry;
303template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
304const typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Initializer
305DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
307template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
308class DispatchMsgBinSearchPolymorphicHelperBase
311 static const std::size_t RegistrySize = std::tuple_size<TAllMessages>::value;
312 using Registry = PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, RegistrySize>;
313 using Initializer = PolymorphicBinSearchDispatchRegistryInitializer<Registry, TAllMessages>;
315 static Registry s_registry;
316 static Initializer s_initializer;
319template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
320typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Registry
321DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_registry;
323template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
324typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Initializer
325DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
327template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
328class DispatchMsgBinSearchStrongPolymorphicHelper :
public
329 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
331 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
332 using Registry =
typename Base::Registry;
334 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
335 using MsgIdParamType =
typename TMsgBase::MsgIdParamType;
336 static auto dispatch(MsgIdParamType
id, TMsgBase& msg, THandler& handler) ->
337 MessageInterfaceDispatchRetType<
338 typename std::decay<
decltype(handler)>::type>
341 static_cast<void>(Base::s_initializer);
344 MessageInterfaceDispatchRetType<
345 typename std::decay<
decltype(handler)>::type>;
349 Base::s_registry.begin(), Base::s_registry.end(),
id,
350 [](
typename Registry::value_type method, MsgIdParamType idParam) ->
bool
353 return method->getId() < idParam;
356 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
357 return static_cast<RetType
>(handler.handle(msg));
360 return static_cast<RetType
>((*iter)->dispatch(msg, handler));
364template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
365class DispatchMsgBinSearchWeakPolymorphicHelper :
public
366 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
368 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
369 using Registry =
typename Base::Registry;
371 template <
typename TId>
372 static auto dispatch(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler) ->
373 MessageInterfaceDispatchRetType<
374 typename std::decay<
decltype(handler)>::type>
377 static_cast<void>(Base::s_initializer);
380 MessageInterfaceDispatchRetType<
381 typename std::decay<
decltype(handler)>::type>;
383 using IdType =
typename std::decay<
decltype(id)>::type;
387 Base::s_registry.begin(), Base::s_registry.end(),
id,
388 [](
typename Registry::value_type method, IdType idParam) ->
bool
391 return static_cast<IdType
>(method->getId()) < idParam;
394 if ((lowerIter == Base::s_registry.end()) ||
395 (
static_cast<IdType
>((*lowerIter)->getId()) != id)) {
396 return static_cast<RetType
>(handler.handle(msg));
401 lowerIter, Base::s_registry.end(),
id,
402 [](IdType idParam,
typename Registry::value_type method)
404 return idParam < static_cast<IdType>(method->getId());
410 auto dist =
static_cast<std::size_t
>(upperIter - lowerIter);
411 if (dist <= offset) {
412 return static_cast<RetType
>(handler.handle(msg));
415 auto actualIter = lowerIter + offset;
416 return static_cast<RetType
>((*actualIter)->dispatch(msg, handler));
420template <
typename TElem,
bool TIsMessage>
421struct DispatchMsgPolymorphicLastIdRetriever;
423template <
typename TElem>
424struct DispatchMsgPolymorphicLastIdRetriever<TElem, true>
426 static_assert(messageHasStaticNumId<TElem>(),
"TElem must define static numeric id");
427 static const std::size_t Value =
428 static_cast<std::size_t
>(TElem::doGetId());
431template <
typename TElem>
432struct DispatchMsgPolymorphicLastIdRetriever<TElem, false>
434 static const std::size_t Value = std::numeric_limits<std::size_t>::max();
437template <
typename TAllMessages, std::
size_t TCount>
438class DispatchMsgPolymorphicIsDirectSuitable
441 typename std::tuple_element<
442 std::tuple_size<TAllMessages>::value - 1,
447 static const std::size_t MaxId =
448 DispatchMsgPolymorphicLastIdRetriever<LastMsg, comms::isMessageBase<LastMsg>()>::Value;
450 static const std::size_t MaxAllowedId = (TCount * 11) / 10;
453 static const bool Value =
454 (MaxId <= (TCount + 10U)) || (MaxId <= MaxAllowedId);
457template <
typename TAllMessages>
458class DispatchMsgPolymorphicIsDirectSuitable<TAllMessages, 0U>
461 static const bool Value =
true;
464template <
typename TAllMessages>
465static constexpr bool dispatchMsgPolymorphicIsDirectSuitable()
468 allMessagesHaveStaticNumId<TAllMessages>() &&
469 DispatchMsgPolymorphicIsDirectSuitable<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
472template <
typename...>
473struct DispatchMsgPolymorphicCompatibleHandlerDetector
475 template <
typename TMsg,
typename THandler>
476 using Type = std::is_base_of<typename TMsg::Handler, THandler>;
479template <
typename TMsg,
typename THandler>
480using DispatchMsgPolymorphicCompatibleHandlerDetectBoolType =
481 typename comms::util::LazyDeepConditional<
484 DispatchMsgPolymorphicCompatibleHandlerDetector,
485 comms::util::FalseType,
490template <
typename TMsg,
typename THandler>
491constexpr bool dispatchMsgPolymorphicIsCompatibleHandler()
493 return DispatchMsgPolymorphicCompatibleHandlerDetectBoolType<TMsg, THandler>::value;
496template <
typename ...>
497class DispatchMsgPolymorphicHelper
499 template <
typename... TParams>
500 using EmptyTag = comms::details::tag::Tag1<>;
502 template <
typename... TParams>
503 using DispatchInterfaceTag = comms::details::tag::Tag2<>;
505 template <
typename... TParams>
506 using DirectTag = comms::details::tag::Tag3<>;
508 template <
typename... TParams>
509 using StrongBinSearchTag = comms::details::tag::Tag4<>;
511 template <
typename... TParams>
512 using WeakBinSearchTag = comms::details::tag::Tag5<>;
514 template <
typename... TParams>
515 using IdInterfaceTag = comms::details::tag::Tag6<>;
517 template <
typename... TParams>
518 using NoIdInterfaceTag = comms::details::tag::Tag7<>;
520 template <
typename TAllMessages,
typename...>
521 using DirectStrongTag =
522 typename comms::util::LazyShallowConditional<
523 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
529 template <
typename TAllMessages,
typename...>
530 using DirectStrongWeakTag =
531 typename comms::util::LazyShallowConditional<
532 allMessagesAreStrongSorted<TAllMessages>()
540 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename...>
542 typename comms::util::LazyShallowConditional<
543 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
545 DispatchInterfaceTag,
550 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename...>
552 typename comms::util::LazyShallowConditional<
553 comms::isMessageBase<TMsgBase>()
557 TAllMessages, TMsgBase, THandler
560 template <
typename TMsgBase,
typename...>
561 using InterfaceDispatchTag =
562 typename comms::util::LazyShallowConditional<
569 template <
typename TMsgBase,
typename THandler,
typename...>
570 using PolymorphicCheckDispatchTag =
571 typename comms::util::LazyShallowConditional<
572 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
575 InterfaceDispatchTag,
580 template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
581 static auto dispatch(TMsgBase& msg, THandler& handler) ->
582 MessageInterfaceDispatchRetType<
583 typename std::decay<
decltype(handler)>::type>
586 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
587 "Message types must be sorted by their ID");
589 static_assert(comms::isMessage<TMsgBase>(),
590 "TMsgBase is expected to be message interface class");
592 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
594 using MsgType =
typename std::decay<
decltype(msg)>::type;
595 using HandlerType =
typename std::decay<
decltype(handler)>::type;
596 using IdRetrieveTag =
597 typename comms::util::LazyShallowConditional<
598 comms::isMessageBase<MsgType>()
601 PolymorphicCheckDispatchTag,
605 return dispatchInternal<TAllMessages>(msg, handler, IdRetrieveTag());
608 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler>
609 static auto dispatch(TId&&
id, TMsgBase& msg, THandler& handler) ->
610 MessageInterfaceDispatchRetType<
611 typename std::decay<
decltype(handler)>::type>
613 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
614 "Message types must be sorted by their ID");
616 static_assert(comms::isMessage<TMsgBase>(),
617 "TMsgBase is expected to be message interface class");
619 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
621 using MsgType =
typename std::decay<
decltype(msg)>::type;
622 using HandlerType =
typename std::decay<
decltype(handler)>::type;
624 dispatchInternal<TAllMessages>(
625 static_cast<typename MsgType::MsgIdParamType
>(
id),
628 AdjustedTag<TAllMessages, MsgType, HandlerType>());
631 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler>
632 static auto dispatch(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler) ->
633 MessageInterfaceDispatchRetType<
634 typename std::decay<
decltype(handler)>::type>
636 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
637 "Message types must be sorted by their ID");
639 static_assert(comms::isMessage<TMsgBase>(),
640 "TMsgBase is expected to be message interface class");
642 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
644 using MsgType =
typename std::decay<
decltype(msg)>::type;
645 using HandlerType =
typename std::decay<
decltype(handler)>::type;
647 dispatchInternal<TAllMessages>(
648 static_cast<typename MsgType::MsgIdParamType
>(
id),
652 AdjustedTag<TAllMessages, MsgType, HandlerType>());
656 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
657 static auto dispatchInternal(TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
658 decltype(handler.handle(msg))
660 return handler.handle(msg);
663 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
664 static auto dispatchInternal(TMsgBase& msg, THandler& handler, IdInterfaceTag<TParams...>) ->
665 MessageInterfaceDispatchRetType<
666 typename std::decay<
decltype(handler)>::type>
668 typename TMsgBase::MsgIdParamType
id = msg.getId();
669 return dispatch<TAllMessages>(
id, msg, handler);
672 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
673 static auto dispatchInternal(TMsgBase& msg, THandler& handler, NoIdInterfaceTag<TParams...>) ->
674 MessageInterfaceDispatchRetType<
675 typename std::decay<
decltype(handler)>::type>
677 static_assert(TMsgBase::hasDispatch(),
"The message must provide polymorphic dispatch");
678 static_assert(std::is_base_of<typename TMsgBase::Handler, THandler>::value,
679 "Incompatible handlers");
681 using RetType = MessageInterfaceDispatchRetType<THandler>;
682 return static_cast<RetType
>(msg.dispatch(handler));
685 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
686 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
687 decltype(handler.handle(msg))
689 static_cast<void>(id);
690 return handler.handle(msg);
693 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
694 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, DispatchInterfaceTag<TParams...>) ->
695 MessageInterfaceDispatchRetType<
696 typename std::decay<
decltype(handler)>::type>
698 static_cast<void>(id);
699 return dispatchInternal<TAllMessages>(msg, handler, NoIdInterfaceTag<>());
702 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
703 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, DirectTag<TParams...>) ->
704 MessageInterfaceDispatchRetType<
705 typename std::decay<
decltype(handler)>::type>
707 using MsgType =
typename std::decay<
decltype(msg)>::type;
708 using HandlerType =
typename std::decay<
decltype(handler)>::type;
710 return DispatchMsgDirectPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
711 dispatch(std::forward<TId>(
id), msg, handler);
714 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
715 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, StrongBinSearchTag<TParams...>) ->
716 MessageInterfaceDispatchRetType<
717 typename std::decay<
decltype(handler)>::type>
719 using MsgType =
typename std::decay<
decltype(msg)>::type;
720 using HandlerType =
typename std::decay<
decltype(handler)>::type;
722 return DispatchMsgBinSearchStrongPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
723 dispatch(std::forward<TId>(
id), msg, handler);
726 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
727 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, WeakBinSearchTag<TParams...>) ->
728 MessageInterfaceDispatchRetType<
729 typename std::decay<
decltype(handler)>::type>
731 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), 0U, msg, handler, WeakBinSearchTag<>());
734 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
735 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, DispatchInterfaceTag<TParams...>) ->
736 MessageInterfaceDispatchRetType<
737 typename std::decay<
decltype(handler)>::type>
739 static_cast<void>(id);
740 static_cast<void>(offset);
741 static_assert(std::is_base_of<typename TMsgBase::Handler, THandler>::value,
742 "Incompatible handlers");
744 using RetType = MessageInterfaceDispatchRetType<THandler>;
745 return static_cast<RetType
>(msg.dispatch(handler));
748 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
749 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
750 decltype(handler.handle(msg))
752 static_cast<void>(id);
753 static_cast<void>(offset);
754 return handler.handle(msg);
757 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
758 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, DirectTag<TParams...>) ->
759 MessageInterfaceDispatchRetType<
760 typename std::decay<
decltype(handler)>::type>
763 using RetType = MessageInterfaceDispatchRetType<THandler>;
764 return static_cast<RetType
>(handler.handle(msg));
767 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), msg, handler, DirectTag<>());
770 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
771 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, StrongBinSearchTag<TParams...>) ->
772 MessageInterfaceDispatchRetType<
773 typename std::decay<
decltype(handler)>::type>
776 using RetType = MessageInterfaceDispatchRetType<THandler>;
777 return static_cast<RetType
>(handler.handle(msg));
780 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), msg, handler, StrongBinSearchTag<>());
783 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
784 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, WeakBinSearchTag<TParams...>) ->
785 MessageInterfaceDispatchRetType<
786 typename std::decay<
decltype(handler)>::type>
788 using MsgType =
typename std::decay<
decltype(msg)>::type;
789 using HandlerType =
typename std::decay<
decltype(handler)>::type;
791 return DispatchMsgBinSearchWeakPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
792 dispatch(std::forward<TId>(
id), offset, msg, handler);
798template <
typename THandler>
799class PolymorphicTypeDirectDispatchMethod
802 PolymorphicTypeDirectDispatchMethod(
const PolymorphicTypeDirectDispatchMethod&) =
delete;
803 PolymorphicTypeDirectDispatchMethod& operator=(
const PolymorphicTypeDirectDispatchMethod&) =
delete;
805 virtual void dispatch(THandler& handler)
const
807 dispatchImpl(handler);
811 PolymorphicTypeDirectDispatchMethod() =
default;
812 ~PolymorphicTypeDirectDispatchMethod() =
default;
814 virtual void dispatchImpl(THandler& handler)
const = 0;
817template <
typename THandler,
typename TMessage>
818class PolymorphicTypeDirectDispatchMethodImpl :
public
819 PolymorphicTypeDirectDispatchMethod<THandler>
822 PolymorphicTypeDirectDispatchMethodImpl() =
default;
823 PolymorphicTypeDirectDispatchMethodImpl(
const PolymorphicTypeDirectDispatchMethodImpl&) =
delete;
824 PolymorphicTypeDirectDispatchMethodImpl& operator=(
const PolymorphicTypeDirectDispatchMethodImpl&) =
delete;
827 virtual void dispatchImpl(THandler& handler)
const
828#ifndef COMMS_COMPILER_GCC47
832 return handler.template handle<TMessage>();
836template <
typename TMsgIdType,
typename THandler>
837class PolymorphicTypeBinSearchDispatchMethod
840 PolymorphicTypeBinSearchDispatchMethod(
const PolymorphicTypeBinSearchDispatchMethod&) =
delete;
841 PolymorphicTypeBinSearchDispatchMethod& operator=(
const PolymorphicTypeBinSearchDispatchMethod&) =
delete;
843 virtual TMsgIdType getId()
const
848 virtual void dispatch(THandler& handler)
const
850 return dispatchImpl(handler);
854 PolymorphicTypeBinSearchDispatchMethod() =
default;
855 ~PolymorphicTypeBinSearchDispatchMethod() =
default;
857 virtual TMsgIdType getIdImpl()
const = 0;
858 virtual void dispatchImpl(THandler& handler)
const = 0;
861template <
typename TMsgIdType,
typename THandler,
typename TMessage>
862class PolymorphicTypeBinSearchDispatchMethodImpl :
public
863 PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>
865 using Base = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
867 PolymorphicTypeBinSearchDispatchMethodImpl() =
default;
868 PolymorphicTypeBinSearchDispatchMethodImpl(
const PolymorphicTypeBinSearchDispatchMethodImpl&) =
delete;
869 PolymorphicTypeBinSearchDispatchMethodImpl& operator=(
const PolymorphicTypeBinSearchDispatchMethodImpl&) =
delete;
871 static TMsgIdType doGetId()
873 return dispatchMsgGetMsgId<TMessage>();
877 virtual TMsgIdType getIdImpl() const
878#ifndef COMMS_COMPILER_GCC47
885 virtual void dispatchImpl(THandler& handler)
const
886#ifndef COMMS_COMPILER_GCC47
890 return handler.template handle<TMessage>();
894template <
typename THandler, std::
size_t TSize>
895using PolymorphicTypeDirectDispatchMsgRegistry =
896 std::array<const PolymorphicTypeDirectDispatchMethod<THandler>*, TSize>;
898template <
typename TMsgIdType,
typename THandler, std::
size_t TSize>
899using PolymorphicTypeBinSearchDispatchMsgRegistry =
900 std::array<const PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>*, TSize>;
902template <
typename THandler>
903class PolymorphicTypeDirectDispatchRegistryFiller
906 using DispatchMethod = PolymorphicTypeDirectDispatchMethod<THandler>;
907 PolymorphicTypeDirectDispatchRegistryFiller(
const DispatchMethod** registry)
908 : m_registry(registry)
912 template <
typename TMessage>
915 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
916 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
917 static const PolymorphicTypeDirectDispatchMethodImpl<THandler, TMessage> Method{};
918 m_registry[
static_cast<std::size_t
>(TMessage::doGetId())] = &Method;
921 const DispatchMethod** m_registry;
924template <
typename THandler, std::
size_t TSize>
925PolymorphicTypeDirectDispatchRegistryFiller<THandler>
926polymorphicTypeDirectDispatchMakeRegistryFiller(
927 PolymorphicTypeDirectDispatchMsgRegistry<THandler, TSize>& registry)
929 return PolymorphicTypeDirectDispatchRegistryFiller<THandler>(®istry[0]);
932template <
typename TRegistry,
typename TAllMessages>
933class PolymorphicTypeDirectDispatchRegistryInitializer
936 PolymorphicTypeDirectDispatchRegistryInitializer() =
delete;
937 PolymorphicTypeDirectDispatchRegistryInitializer(
const PolymorphicTypeDirectDispatchRegistryInitializer&) =
delete;
938 explicit PolymorphicTypeDirectDispatchRegistryInitializer(TRegistry& registry)
940 std::fill(registry.begin(), registry.end(),
nullptr);
941 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeDirectDispatchMakeRegistryFiller(registry));
945template <
typename TMsgIdType,
typename THandler>
946class PolymorphicTypeBinSearchDispatchRegistryFiller
949 using DispatchMethod = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
950 PolymorphicTypeBinSearchDispatchRegistryFiller(
const DispatchMethod** registry)
951 : m_registry(registry)
955 template <
typename TMessage>
960 static const PolymorphicTypeBinSearchDispatchMethodImpl<TMsgIdType, THandler, TMessage> Method{};
961 m_registry[m_idx] = &Method;
966 const DispatchMethod** m_registry;
967 std::size_t m_idx = 0U;
970template <
typename TMsgIdType,
typename THandler, std::
size_t TSize>
971PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>
972polymorphicTypeBinSearchDispatchMakeRegistryFiller(
973 PolymorphicTypeBinSearchDispatchMsgRegistry<TMsgIdType, THandler, TSize>& registry)
975 return PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>(®istry[0]);
978template <
typename TRegistry,
typename TAllMessages>
979class PolymorphicTypeBinSearchDispatchRegistryInitializer
982 explicit PolymorphicTypeBinSearchDispatchRegistryInitializer(TRegistry& registry)
984 std::fill(registry.begin(), registry.end(),
nullptr);
985 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeBinSearchDispatchMakeRegistryFiller(registry));
989template <
typename TAllMessages,
typename THandler>
990class DispatchMsgTypeDirectPolymorphicHelper
993 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
994 static_assert(FirstMsgType::hasMsgIdType(),
"Message interface class must define its id type");
995 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
996 static bool dispatch(MsgIdParamType
id, THandler& handler)
999 static_cast<void>(s_initializer);
1001 auto regIdx =
static_cast<std::size_t
>(id);
1002 if ((s_registry.size() <= regIdx) ||
1003 (s_registry[regIdx] ==
nullptr)) {
1007 s_registry[regIdx]->dispatch(handler);
1012 static const std::size_t RegistrySize =
1013 PolymorphicDirectDispatchRegSizeDetect<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
1014 using Registry = PolymorphicTypeDirectDispatchMsgRegistry<THandler, RegistrySize>;
1015 using Initializer = PolymorphicTypeDirectDispatchRegistryInitializer<Registry, TAllMessages>;
1017 static Registry s_registry;
1018 static const Initializer s_initializer;
1021template <
typename TAllMessages,
typename THandler>
1022typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Registry
1023DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_registry;
1025template <
typename TAllMessages,
typename THandler>
1026const typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Initializer
1027DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_initializer(s_registry);
1029template <
typename TAllMessages,
typename THandler>
1030class DispatchMsgTypeBinSearchPolymorphicHelperBase
1033 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1034 static_assert(comms::isMessage<FirstMsgType>(),
1035 "The type in the tuple are expected to be proper messages");
1036 static_assert(FirstMsgType::hasMsgIdType(),
"Message interface class must define its id type");
1037 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1039 static const std::size_t RegistrySize = std::tuple_size<TAllMessages>::value;
1040 using Registry = PolymorphicTypeBinSearchDispatchMsgRegistry<MsgIdParamType, THandler, RegistrySize>;
1041 using Initializer = PolymorphicTypeBinSearchDispatchRegistryInitializer<Registry, TAllMessages>;
1043 static Registry s_registry;
1044 static Initializer s_initializer;
1047template <
typename TAllMessages,
typename THandler>
1048typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Registry
1049DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_registry;
1051template <
typename TAllMessages,
typename THandler>
1052typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Initializer
1053DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_initializer(s_registry);
1055template <
typename TAllMessages,
typename THandler>
1056class DispatchMsgTypeBinSearchStrongPolymorphicHelper :
public
1057 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1059 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1060 using Registry =
typename Base::Registry;
1062 using MsgIdParamType =
typename Base::MsgIdParamType;
1063 static bool dispatch(MsgIdParamType
id, THandler& handler)
1066 static_cast<void>(Base::s_initializer);
1070 Base::s_registry.begin(), Base::s_registry.end(),
id,
1071 [](
typename Registry::value_type method, MsgIdParamType idParam) ->
bool
1074 return method->getId() < idParam;
1077 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
1081 (*iter)->dispatch(handler);
1086template <
typename TAllMessages,
typename THandler>
1087class DispatchMsgTypeBinSearchWeakPolymorphicHelper :
public
1088 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1090 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1091 using Registry =
typename Base::Registry;
1094 using MsgIdParamType =
typename Base::MsgIdParamType;
1095 static bool dispatch(MsgIdParamType
id, std::size_t offset, THandler& handler)
1098 static_cast<void>(Base::s_initializer);
1100 using IdType =
typename std::decay<
decltype(id)>::type;
1103 Base::s_registry.begin(), Base::s_registry.end(),
id,
1104 [](
typename Registry::value_type method, IdType idParam) ->
bool
1107 return static_cast<IdType
>(method->getId()) < idParam;
1110 if ((lowerIter == Base::s_registry.end()) ||
1111 (
static_cast<IdType
>((*lowerIter)->getId()) != id)) {
1117 lowerIter, Base::s_registry.end(),
id,
1118 [](IdType idParam,
typename Registry::value_type method)
1120 return idParam < static_cast<IdType>(method->getId());
1126 auto dist =
static_cast<std::size_t
>(upperIter - lowerIter);
1127 if (dist <= offset) {
1131 auto actualIter = lowerIter + offset;
1132 (*actualIter)->dispatch(handler);
1137template <
typename...>
1138class DispatchMsgTypePolymorphicHelper
1140 template <
typename... TParams>
1141 using EmptyTag = comms::details::tag::Tag1<>;
1143 template <
typename... TParams>
1144 using DirectTag = comms::details::tag::Tag2<>;
1146 template <
typename... TParams>
1147 using StrongBinSearchTag = comms::details::tag::Tag3<>;
1149 template <
typename... TParams>
1150 using WeakBinSearchTag = comms::details::tag::Tag4<>;
1152 template <
typename TAllMessages,
typename...>
1153 using DirectStrongTag =
1154 typename comms::util::LazyShallowConditional<
1155 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
1161 template <
typename TAllMessages,
typename...>
1162 using DirectStrongWeakTag =
1163 typename comms::util::LazyShallowConditional<
1164 allMessagesAreStrongSorted<TAllMessages>()
1172 template <
typename TAllMessages,
typename...>
1174 typename comms::util::LazyShallowConditional<
1175 std::tuple_size<TAllMessages>::value == 0U
1178 DirectStrongWeakTag,
1183 template <
typename TAllMessages,
typename TId,
typename THandler>
1184 static bool dispatch(TId&&
id, THandler& handler)
1186 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1187 "Message types must be sorted by their ID");
1189 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, Tag<TAllMessages>());
1192 template <
typename TAllMessages,
typename TId,
typename THandler>
1193 static bool dispatch(TId&&
id, std::size_t offset, THandler& handler)
1195 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1196 "Message types must be sorted by their ID");
1198 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), offset, handler, Tag<TAllMessages>());
1203 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1204 static bool dispatchInternal(TId&&
id, THandler& handler, EmptyTag<TParams...>)
1206 static_cast<void>(id);
1207 static_cast<void>(handler);
1211 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1212 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, EmptyTag<TParams...>)
1214 static_cast<void>(id);
1215 static_cast<void>(handler);
1216 static_cast<void>(offset);
1220 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1221 static bool dispatchInternal(TId&&
id, THandler& handler, DirectTag<TParams...>)
1223 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1224 static_assert(comms::isMessage<FirstMsgType>(),
1225 "The type in the tuple are expected to be proper messages");
1226 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1227 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1228 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1229 return DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, HandlerType>::
1230 dispatch(
static_cast<MsgIdParamType
>(
id), handler);
1233 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1234 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, DirectTag<TParams...>)
1240 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, DirectTag<>());
1243 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1244 static bool dispatchInternal(TId&&
id, THandler& handler, StrongBinSearchTag<TParams...>)
1246 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1247 static_assert(comms::isMessage<FirstMsgType>(),
1248 "The type in the tuple are expected to be proper messages");
1249 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1250 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1251 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1252 return DispatchMsgTypeBinSearchStrongPolymorphicHelper<TAllMessages, HandlerType>::
1253 dispatch(
static_cast<MsgIdParamType
>(
id), handler);
1256 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1257 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, StrongBinSearchTag<TParams...>)
1263 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, StrongBinSearchTag<>());
1266 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1267 static bool dispatchInternal(TId&&
id, THandler& handler, WeakBinSearchTag<TParams...>)
1269 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), 0U, handler, WeakBinSearchTag<>());
1272 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1273 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, WeakBinSearchTag<TParams...>)
1275 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1276 static_assert(comms::isMessage<FirstMsgType>(),
1277 "The type in the tuple are expected to be proper messages");
1278 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1279 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1280 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1281 return DispatchMsgTypeBinSearchWeakPolymorphicHelper<TAllMessages, HandlerType>::
1282 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:1487
comms::option::def::MsgIdType< T > MsgIdType
Same as comms::option::def::MsgIdType.
Definition options.h:1473
Main namespace for all classes / functions of COMMS library.
Replacement to some types from standard type_traits.