15#include "comms/details/DispatchMsgIdRetrieveHelper.h"
16#include "comms/details/tag.h"
35template <
typename TMsgBase,
typename THandler>
36class PolymorphicDirectDispatchMethod
39 PolymorphicDirectDispatchMethod(
const PolymorphicDirectDispatchMethod&) =
delete;
40 PolymorphicDirectDispatchMethod& operator=(
const PolymorphicDirectDispatchMethod&) =
delete;
42 virtual auto dispatch(TMsgBase& msg, THandler& handler)
const ->
43 MessageInterfaceDispatchRetType<THandler>
45 return dispatchImpl(msg, handler);
49 PolymorphicDirectDispatchMethod() =
default;
50 ~PolymorphicDirectDispatchMethod() =
default;
52 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
53 MessageInterfaceDispatchRetType<THandler> = 0;
56template <
typename TMsgBase,
typename THandler,
typename TMessage>
57class PolymorphicDirectDispatchMethodImpl :
public
58 PolymorphicDirectDispatchMethod<TMsgBase, THandler>
61 PolymorphicDirectDispatchMethodImpl() =
default;
62 PolymorphicDirectDispatchMethodImpl(
const PolymorphicDirectDispatchMethodImpl&) =
delete;
63 PolymorphicDirectDispatchMethodImpl& operator=(
const PolymorphicDirectDispatchMethodImpl&) =
delete;
66 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
67 MessageInterfaceDispatchRetType<THandler>
68#ifndef COMMS_COMPILER_GCC47
72 static_assert(std::is_base_of<TMsgBase, TMessage>::value,
"TMessage must extend TMsgBase");
73 auto& castedMsg =
static_cast<TMessage&
>(msg);
74 return handler.handle(castedMsg);
78template <
typename TMsgBase,
typename THandler>
79class PolymorphicBinSearchDispatchMethod
82 PolymorphicBinSearchDispatchMethod(
const PolymorphicBinSearchDispatchMethod&) =
delete;
83 PolymorphicBinSearchDispatchMethod& operator=(
const PolymorphicBinSearchDispatchMethod&) =
delete;
85 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
86 using MsgIdParamType =
typename TMsgBase::MsgIdParamType;
87 using MsgIdType =
typename TMsgBase::MsgIdType;
89 virtual MsgIdParamType getId()
const
94 virtual auto dispatch(TMsgBase& msg, THandler& handler)
const ->
95 MessageInterfaceDispatchRetType<THandler>
97 return dispatchImpl(msg, handler);
101 PolymorphicBinSearchDispatchMethod() =
default;
102 ~PolymorphicBinSearchDispatchMethod() =
default;
104 virtual MsgIdParamType getIdImpl()
const = 0;
105 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
106 MessageInterfaceDispatchRetType<THandler> = 0;
109template <
typename TMsgBase,
typename THandler,
typename TMessage>
110class PolymorphicBinSearchDispatchMethodImpl :
public
111 PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>
113 using Base = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
115 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
116 using MsgIdParamType =
typename Base::MsgIdParamType;
117 using MsgIdType =
typename Base::MsgIdType;
119 PolymorphicBinSearchDispatchMethodImpl() =
default;
120 PolymorphicBinSearchDispatchMethodImpl(
const PolymorphicBinSearchDispatchMethodImpl&) =
delete;
121 PolymorphicBinSearchDispatchMethodImpl& operator=(
const PolymorphicBinSearchDispatchMethodImpl&) =
delete;
123 static MsgIdParamType doGetId()
125 return dispatchMsgGetMsgId<TMessage>();
130 virtual MsgIdParamType getIdImpl() const
131#ifndef COMMS_COMPILER_GCC47
138 virtual auto dispatchImpl(TMsgBase& msg, THandler& handler)
const ->
139 MessageInterfaceDispatchRetType<THandler>
140#ifndef COMMS_COMPILER_GCC47
144 static_assert(std::is_base_of<TMsgBase, TMessage>::value,
"TMessage must extend TMsgBase");
145 auto& castedMsg =
static_cast<TMessage&
>(msg);
146 return handler.handle(castedMsg);
150template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
151using PolymorphicDirectDispatchMsgRegistry =
152 std::array<const PolymorphicDirectDispatchMethod<TMsgBase, THandler>*, TSize>;
154template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
155using PolymorphicBinSearchDispatchMsgRegistry =
156 std::array<const PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>*, TSize>;
158template <
typename TMsgBase,
typename THandler>
159class PolymorphicDirectDispatchRegistryFiller
162 using DispatchMethod = PolymorphicDirectDispatchMethod<TMsgBase, THandler>;
163 PolymorphicDirectDispatchRegistryFiller(
const DispatchMethod** registry)
164 : m_registry(registry)
168 template <
typename TMessage>
171 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
172 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
173 static const PolymorphicDirectDispatchMethodImpl<TMsgBase, THandler, TMessage> Method{};
174 m_registry[
static_cast<std::size_t
>(TMessage::doGetId())] = &Method;
177 const DispatchMethod** m_registry;
180template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
181PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>
182polymorphicDirectDispatchMakeRegistryFiller(
183 PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
185 return PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>(®istry[0]);
188template <
typename TRegistry,
typename TAllMessages>
189class PolymorphicDirectDispatchRegistryInitializer
192 PolymorphicDirectDispatchRegistryInitializer() =
delete;
193 PolymorphicDirectDispatchRegistryInitializer(
const PolymorphicDirectDispatchRegistryInitializer&) =
delete;
194 explicit PolymorphicDirectDispatchRegistryInitializer(TRegistry& registry)
196 std::fill(registry.begin(), registry.end(),
nullptr);
197 comms::util::tupleForEachType<TAllMessages>(polymorphicDirectDispatchMakeRegistryFiller(registry));
201template <
typename TMsgBase,
typename THandler>
202class PolymorphicBinSearchDispatchRegistryFiller
205 using DispatchMethod = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
206 PolymorphicBinSearchDispatchRegistryFiller(
const DispatchMethod** registry)
207 : m_registry(registry)
211 template <
typename TMessage>
214 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
215 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
216 static const PolymorphicBinSearchDispatchMethodImpl<TMsgBase, THandler, TMessage> Method{};
217 m_registry[m_idx] = &Method;
222 const DispatchMethod** m_registry;
223 std::size_t m_idx = 0U;
226template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
227PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>
228polymorphicBinSearchDispatchMakeRegistryFiller(
229 PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
231 return PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>(®istry[0]);
234template <
typename TRegistry,
typename TAllMessages>
235class PolymorphicBinSearchDispatchRegistryInitializer
238 explicit PolymorphicBinSearchDispatchRegistryInitializer(TRegistry& registry)
240 std::fill(registry.begin(), registry.end(),
nullptr);
241 comms::util::tupleForEachType<TAllMessages>(polymorphicBinSearchDispatchMakeRegistryFiller(registry));
245template <
typename TAllMessages, std::
size_t TMaxSize>
246class PolymorphicDirectDispatchRegSizeDetect
248 using MsgType =
typename std::tuple_element<TMaxSize - 1, TAllMessages>::type;
249 static_assert(comms::isMessageBase<MsgType>(),
"Must be actual message");
250 static_assert(messageHasStaticNumId<MsgType>(),
"Message must define static numeric ID");
251 static_assert(MsgType::hasMsgIdType(),
"Message interface class must define its id type");
252 static const typename MsgType::MsgIdParamType MsgId = MsgType::doGetId();
254 static const std::size_t Value =
static_cast<std::size_t
>(MsgId) + 1U;
257template <
typename TAllMessages>
258class PolymorphicDirectDispatchRegSizeDetect<TAllMessages, 0U>
261 static const std::size_t Value = 0;
264template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
265class DispatchMsgDirectPolymorphicHelper
268 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
269 using MsgIdParamType =
typename TMsgBase::MsgIdParamType;
270 static auto dispatch(MsgIdParamType
id, TMsgBase& msg, THandler& handler) ->
271 MessageInterfaceDispatchRetType<
272 typename std::decay<
decltype(handler)>::type>
275 static_cast<void>(s_initializer);
278 MessageInterfaceDispatchRetType<
279 typename std::decay<
decltype(handler)>::type>;
281 auto regIdx =
static_cast<std::size_t
>(id);
282 if ((s_registry.size() <= regIdx) ||
283 (s_registry[regIdx] ==
nullptr)) {
284 return static_cast<RetType
>(handler.handle(msg));
287 return static_cast<RetType
>(s_registry[regIdx]->dispatch(msg, handler));
291 static const std::size_t RegistrySize =
292 PolymorphicDirectDispatchRegSizeDetect<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
293 using Registry = PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, RegistrySize>;
294 using Initializer = PolymorphicDirectDispatchRegistryInitializer<Registry, TAllMessages>;
296 static Registry s_registry;
297 static const Initializer s_initializer;
300template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
301typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Registry
302DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_registry;
304template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
305const typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Initializer
306DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
308template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
309class DispatchMsgBinSearchPolymorphicHelperBase
312 static const std::size_t RegistrySize = std::tuple_size<TAllMessages>::value;
313 using Registry = PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, RegistrySize>;
314 using Initializer = PolymorphicBinSearchDispatchRegistryInitializer<Registry, TAllMessages>;
316 static Registry s_registry;
317 static Initializer s_initializer;
320template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
321typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Registry
322DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_registry;
324template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
325typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Initializer
326DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
328template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
329class DispatchMsgBinSearchStrongPolymorphicHelper :
public
330 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
332 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
333 using Registry =
typename Base::Registry;
335 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
336 using MsgIdParamType =
typename TMsgBase::MsgIdParamType;
337 static auto dispatch(MsgIdParamType
id, TMsgBase& msg, THandler& handler) ->
338 MessageInterfaceDispatchRetType<
339 typename std::decay<
decltype(handler)>::type>
342 static_cast<void>(Base::s_initializer);
345 MessageInterfaceDispatchRetType<
346 typename std::decay<
decltype(handler)>::type>;
350 Base::s_registry.begin(), Base::s_registry.end(),
id,
351 [](
typename Registry::value_type method, MsgIdParamType idParam) ->
bool
354 return method->getId() < idParam;
357 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
358 return static_cast<RetType
>(handler.handle(msg));
361 return static_cast<RetType
>((*iter)->dispatch(msg, handler));
365template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
366class DispatchMsgBinSearchWeakPolymorphicHelper :
public
367 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
369 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
370 using Registry =
typename Base::Registry;
372 template <
typename TId>
373 static auto dispatch(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler) ->
374 MessageInterfaceDispatchRetType<
375 typename std::decay<
decltype(handler)>::type>
378 static_cast<void>(Base::s_initializer);
381 MessageInterfaceDispatchRetType<
382 typename std::decay<
decltype(handler)>::type>;
384 using IdType =
typename std::decay<
decltype(id)>::type;
388 Base::s_registry.begin(), Base::s_registry.end(),
id,
389 [](
typename Registry::value_type method, IdType idParam) ->
bool
392 return static_cast<IdType
>(method->getId()) < idParam;
395 if ((lowerIter == Base::s_registry.end()) ||
396 (
static_cast<IdType
>((*lowerIter)->getId()) != id)) {
397 return static_cast<RetType
>(handler.handle(msg));
402 lowerIter, Base::s_registry.end(),
id,
403 [](IdType idParam,
typename Registry::value_type method)
405 return idParam < static_cast<IdType>(method->getId());
411 auto dist =
static_cast<std::size_t
>(upperIter - lowerIter);
412 if (dist <= offset) {
413 return static_cast<RetType
>(handler.handle(msg));
416 auto actualIter = lowerIter + offset;
417 return static_cast<RetType
>((*actualIter)->dispatch(msg, handler));
421template <
typename TElem,
bool TIsMessage>
422struct DispatchMsgPolymorphicLastIdRetriever;
424template <
typename TElem>
425struct DispatchMsgPolymorphicLastIdRetriever<TElem, true>
427 static_assert(messageHasStaticNumId<TElem>(),
"TElem must define static numeric id");
428 static const std::size_t Value =
429 static_cast<std::size_t
>(TElem::doGetId());
432template <
typename TElem>
433struct DispatchMsgPolymorphicLastIdRetriever<TElem, false>
435 static const std::size_t Value = std::numeric_limits<std::size_t>::max();
438template <
typename TAllMessages, std::
size_t TCount>
439class DispatchMsgPolymorphicIsDirectSuitable
442 typename std::tuple_element<
443 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,
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>()
538 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename...>
540 typename comms::util::LazyShallowConditional<
541 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
543 DispatchInterfaceTag,
548 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename...>
550 typename comms::util::LazyShallowConditional<
551 comms::isMessageBase<TMsgBase>()
555 TAllMessages, TMsgBase, THandler
558 template <
typename TMsgBase,
typename...>
559 using InterfaceDispatchTag =
560 typename comms::util::LazyShallowConditional<
567 template <
typename TMsgBase,
typename THandler,
typename...>
568 using PolymorphicCheckDispatchTag =
569 typename comms::util::LazyShallowConditional<
570 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
573 InterfaceDispatchTag,
578 template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
579 static auto dispatch(TMsgBase& msg, THandler& handler) ->
580 MessageInterfaceDispatchRetType<
581 typename std::decay<
decltype(handler)>::type>
584 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
585 "Message types must be sorted by their ID");
587 static_assert(comms::isMessage<TMsgBase>(),
588 "TMsgBase is expected to be message interface class");
590 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
592 using MsgType =
typename std::decay<
decltype(msg)>::type;
593 using HandlerType =
typename std::decay<
decltype(handler)>::type;
594 using IdRetrieveTag =
595 typename comms::util::LazyShallowConditional<
596 comms::isMessageBase<MsgType>()
599 PolymorphicCheckDispatchTag,
603 return dispatchInternal<TAllMessages>(msg, handler, IdRetrieveTag());
606 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler>
607 static auto dispatch(TId&&
id, TMsgBase& msg, THandler& handler) ->
608 MessageInterfaceDispatchRetType<
609 typename std::decay<
decltype(handler)>::type>
611 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
612 "Message types must be sorted by their ID");
614 static_assert(comms::isMessage<TMsgBase>(),
615 "TMsgBase is expected to be message interface class");
617 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
619 using MsgType =
typename std::decay<
decltype(msg)>::type;
620 using HandlerType =
typename std::decay<
decltype(handler)>::type;
622 dispatchInternal<TAllMessages>(
623 static_cast<typename MsgType::MsgIdParamType
>(
id),
626 AdjustedTag<TAllMessages, MsgType, HandlerType>());
629 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler>
630 static auto dispatch(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler) ->
631 MessageInterfaceDispatchRetType<
632 typename std::decay<
decltype(handler)>::type>
634 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
635 "Message types must be sorted by their ID");
637 static_assert(comms::isMessage<TMsgBase>(),
638 "TMsgBase is expected to be message interface class");
640 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
642 using MsgType =
typename std::decay<
decltype(msg)>::type;
643 using HandlerType =
typename std::decay<
decltype(handler)>::type;
645 dispatchInternal<TAllMessages>(
646 static_cast<typename MsgType::MsgIdParamType
>(
id),
650 AdjustedTag<TAllMessages, MsgType, HandlerType>());
654 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
655 static auto dispatchInternal(TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
656 decltype(handler.handle(msg))
658 return handler.handle(msg);
661 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
662 static auto dispatchInternal(TMsgBase& msg, THandler& handler, IdInterfaceTag<TParams...>) ->
663 MessageInterfaceDispatchRetType<
664 typename std::decay<
decltype(handler)>::type>
666 typename TMsgBase::MsgIdParamType
id = msg.getId();
667 return dispatch<TAllMessages>(
id, msg, handler);
670 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
671 static auto dispatchInternal(TMsgBase& msg, THandler& handler, NoIdInterfaceTag<TParams...>) ->
672 MessageInterfaceDispatchRetType<
673 typename std::decay<
decltype(handler)>::type>
675 static_assert(TMsgBase::hasDispatch(),
"The message must provide polymorphic dispatch");
676 static_assert(std::is_base_of<typename TMsgBase::Handler, THandler>::value,
677 "Incompatible handlers");
679 using RetType = MessageInterfaceDispatchRetType<THandler>;
680 return static_cast<RetType
>(msg.dispatch(handler));
683 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
684 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
685 decltype(handler.handle(msg))
687 static_cast<void>(id);
688 return handler.handle(msg);
691 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
692 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, DispatchInterfaceTag<TParams...>) ->
693 MessageInterfaceDispatchRetType<
694 typename std::decay<
decltype(handler)>::type>
696 static_cast<void>(id);
697 return dispatchInternal<TAllMessages>(msg, handler, NoIdInterfaceTag<>());
700 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
701 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, DirectTag<TParams...>) ->
702 MessageInterfaceDispatchRetType<
703 typename std::decay<
decltype(handler)>::type>
705 using MsgType =
typename std::decay<
decltype(msg)>::type;
706 using HandlerType =
typename std::decay<
decltype(handler)>::type;
708 return DispatchMsgDirectPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
709 dispatch(std::forward<TId>(
id), msg, handler);
712 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
713 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, StrongBinSearchTag<TParams...>) ->
714 MessageInterfaceDispatchRetType<
715 typename std::decay<
decltype(handler)>::type>
717 using MsgType =
typename std::decay<
decltype(msg)>::type;
718 using HandlerType =
typename std::decay<
decltype(handler)>::type;
720 return DispatchMsgBinSearchStrongPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
721 dispatch(std::forward<TId>(
id), msg, handler);
724 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
725 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, WeakBinSearchTag<TParams...>) ->
726 MessageInterfaceDispatchRetType<
727 typename std::decay<
decltype(handler)>::type>
729 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), 0U, msg, handler, WeakBinSearchTag<>());
732 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
733 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, DispatchInterfaceTag<TParams...>) ->
734 MessageInterfaceDispatchRetType<
735 typename std::decay<
decltype(handler)>::type>
737 static_cast<void>(id);
738 static_cast<void>(offset);
739 static_assert(std::is_base_of<typename TMsgBase::Handler, THandler>::value,
740 "Incompatible handlers");
742 using RetType = MessageInterfaceDispatchRetType<THandler>;
743 return static_cast<RetType
>(msg.dispatch(handler));
746 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
747 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
748 decltype(handler.handle(msg))
750 static_cast<void>(id);
751 static_cast<void>(offset);
752 return handler.handle(msg);
755 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
756 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, DirectTag<TParams...>) ->
757 MessageInterfaceDispatchRetType<
758 typename std::decay<
decltype(handler)>::type>
761 using RetType = MessageInterfaceDispatchRetType<THandler>;
762 return static_cast<RetType
>(handler.handle(msg));
765 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), msg, handler, DirectTag<>());
768 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
769 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, StrongBinSearchTag<TParams...>) ->
770 MessageInterfaceDispatchRetType<
771 typename std::decay<
decltype(handler)>::type>
774 using RetType = MessageInterfaceDispatchRetType<THandler>;
775 return static_cast<RetType
>(handler.handle(msg));
778 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), msg, handler, StrongBinSearchTag<>());
781 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
782 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, WeakBinSearchTag<TParams...>) ->
783 MessageInterfaceDispatchRetType<
784 typename std::decay<
decltype(handler)>::type>
786 using MsgType =
typename std::decay<
decltype(msg)>::type;
787 using HandlerType =
typename std::decay<
decltype(handler)>::type;
789 return DispatchMsgBinSearchWeakPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
790 dispatch(std::forward<TId>(
id), offset, msg, handler);
796template <
typename THandler>
797class PolymorphicTypeDirectDispatchMethod
800 PolymorphicTypeDirectDispatchMethod(
const PolymorphicTypeDirectDispatchMethod&) =
delete;
801 PolymorphicTypeDirectDispatchMethod& operator=(
const PolymorphicTypeDirectDispatchMethod&) =
delete;
803 virtual void dispatch(THandler& handler)
const
805 dispatchImpl(handler);
809 PolymorphicTypeDirectDispatchMethod() =
default;
810 ~PolymorphicTypeDirectDispatchMethod() =
default;
812 virtual void dispatchImpl(THandler& handler)
const = 0;
815template <
typename THandler,
typename TMessage>
816class PolymorphicTypeDirectDispatchMethodImpl :
public
817 PolymorphicTypeDirectDispatchMethod<THandler>
820 PolymorphicTypeDirectDispatchMethodImpl() =
default;
821 PolymorphicTypeDirectDispatchMethodImpl(
const PolymorphicTypeDirectDispatchMethodImpl&) =
delete;
822 PolymorphicTypeDirectDispatchMethodImpl& operator=(
const PolymorphicTypeDirectDispatchMethodImpl&) =
delete;
825 virtual void dispatchImpl(THandler& handler)
const
826#ifndef COMMS_COMPILER_GCC47
830 return handler.template handle<TMessage>();
834template <
typename TMsgIdType,
typename THandler>
835class PolymorphicTypeBinSearchDispatchMethod
838 PolymorphicTypeBinSearchDispatchMethod(
const PolymorphicTypeBinSearchDispatchMethod&) =
delete;
839 PolymorphicTypeBinSearchDispatchMethod& operator=(
const PolymorphicTypeBinSearchDispatchMethod&) =
delete;
841 virtual TMsgIdType getId()
const
846 virtual void dispatch(THandler& handler)
const
848 return dispatchImpl(handler);
852 PolymorphicTypeBinSearchDispatchMethod() =
default;
853 ~PolymorphicTypeBinSearchDispatchMethod() =
default;
855 virtual TMsgIdType getIdImpl()
const = 0;
856 virtual void dispatchImpl(THandler& handler)
const = 0;
859template <
typename TMsgIdType,
typename THandler,
typename TMessage>
860class PolymorphicTypeBinSearchDispatchMethodImpl :
public
861 PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>
863 using Base = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
865 PolymorphicTypeBinSearchDispatchMethodImpl() =
default;
866 PolymorphicTypeBinSearchDispatchMethodImpl(
const PolymorphicTypeBinSearchDispatchMethodImpl&) =
delete;
867 PolymorphicTypeBinSearchDispatchMethodImpl& operator=(
const PolymorphicTypeBinSearchDispatchMethodImpl&) =
delete;
869 static TMsgIdType doGetId()
871 return dispatchMsgGetMsgId<TMessage>();
875 virtual TMsgIdType getIdImpl() const
876#ifndef COMMS_COMPILER_GCC47
883 virtual void dispatchImpl(THandler& handler)
const
884#ifndef COMMS_COMPILER_GCC47
888 return handler.template handle<TMessage>();
892template <
typename THandler, std::
size_t TSize>
893using PolymorphicTypeDirectDispatchMsgRegistry =
894 std::array<const PolymorphicTypeDirectDispatchMethod<THandler>*, TSize>;
896template <
typename TMsgIdType,
typename THandler, std::
size_t TSize>
897using PolymorphicTypeBinSearchDispatchMsgRegistry =
898 std::array<const PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>*, TSize>;
900template <
typename THandler>
901class PolymorphicTypeDirectDispatchRegistryFiller
904 using DispatchMethod = PolymorphicTypeDirectDispatchMethod<THandler>;
905 PolymorphicTypeDirectDispatchRegistryFiller(
const DispatchMethod** registry)
906 : m_registry(registry)
910 template <
typename TMessage>
913 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
914 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
915 static const PolymorphicTypeDirectDispatchMethodImpl<THandler, TMessage> Method{};
916 m_registry[
static_cast<std::size_t
>(TMessage::doGetId())] = &Method;
919 const DispatchMethod** m_registry;
922template <
typename THandler, std::
size_t TSize>
923PolymorphicTypeDirectDispatchRegistryFiller<THandler>
924polymorphicTypeDirectDispatchMakeRegistryFiller(
925 PolymorphicTypeDirectDispatchMsgRegistry<THandler, TSize>& registry)
927 return PolymorphicTypeDirectDispatchRegistryFiller<THandler>(®istry[0]);
930template <
typename TRegistry,
typename TAllMessages>
931class PolymorphicTypeDirectDispatchRegistryInitializer
934 PolymorphicTypeDirectDispatchRegistryInitializer() =
delete;
935 PolymorphicTypeDirectDispatchRegistryInitializer(
const PolymorphicTypeDirectDispatchRegistryInitializer&) =
delete;
936 explicit PolymorphicTypeDirectDispatchRegistryInitializer(TRegistry& registry)
938 std::fill(registry.begin(), registry.end(),
nullptr);
939 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeDirectDispatchMakeRegistryFiller(registry));
943template <
typename TMsgIdType,
typename THandler>
944class PolymorphicTypeBinSearchDispatchRegistryFiller
947 using DispatchMethod = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
948 PolymorphicTypeBinSearchDispatchRegistryFiller(
const DispatchMethod** registry)
949 : m_registry(registry)
953 template <
typename TMessage>
958 static const PolymorphicTypeBinSearchDispatchMethodImpl<TMsgIdType, THandler, TMessage> Method{};
959 m_registry[m_idx] = &Method;
964 const DispatchMethod** m_registry;
965 std::size_t m_idx = 0U;
968template <
typename TMsgIdType,
typename THandler, std::
size_t TSize>
969PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>
970polymorphicTypeBinSearchDispatchMakeRegistryFiller(
971 PolymorphicTypeBinSearchDispatchMsgRegistry<TMsgIdType, THandler, TSize>& registry)
973 return PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>(®istry[0]);
976template <
typename TRegistry,
typename TAllMessages>
977class PolymorphicTypeBinSearchDispatchRegistryInitializer
980 explicit PolymorphicTypeBinSearchDispatchRegistryInitializer(TRegistry& registry)
982 std::fill(registry.begin(), registry.end(),
nullptr);
983 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeBinSearchDispatchMakeRegistryFiller(registry));
987template <
typename TAllMessages,
typename THandler>
988class DispatchMsgTypeDirectPolymorphicHelper
991 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
992 static_assert(FirstMsgType::hasMsgIdType(),
"Message interface class must define its id type");
993 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
994 static bool dispatch(MsgIdParamType
id, THandler& handler)
997 static_cast<void>(s_initializer);
999 auto regIdx =
static_cast<std::size_t
>(id);
1000 if ((s_registry.size() <= regIdx) ||
1001 (s_registry[regIdx] ==
nullptr)) {
1005 s_registry[regIdx]->dispatch(handler);
1010 static const std::size_t RegistrySize =
1011 PolymorphicDirectDispatchRegSizeDetect<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
1012 using Registry = PolymorphicTypeDirectDispatchMsgRegistry<THandler, RegistrySize>;
1013 using Initializer = PolymorphicTypeDirectDispatchRegistryInitializer<Registry, TAllMessages>;
1015 static Registry s_registry;
1016 static const Initializer s_initializer;
1019template <
typename TAllMessages,
typename THandler>
1020typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Registry
1021DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_registry;
1023template <
typename TAllMessages,
typename THandler>
1024const typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Initializer
1025DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_initializer(s_registry);
1027template <
typename TAllMessages,
typename THandler>
1028class DispatchMsgTypeBinSearchPolymorphicHelperBase
1031 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1032 static_assert(comms::isMessage<FirstMsgType>(),
1033 "The type in the tuple are expected to be proper messages");
1034 static_assert(FirstMsgType::hasMsgIdType(),
"Message interface class must define its id type");
1035 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1037 static const std::size_t RegistrySize = std::tuple_size<TAllMessages>::value;
1038 using Registry = PolymorphicTypeBinSearchDispatchMsgRegistry<MsgIdParamType, THandler, RegistrySize>;
1039 using Initializer = PolymorphicTypeBinSearchDispatchRegistryInitializer<Registry, TAllMessages>;
1041 static Registry s_registry;
1042 static Initializer s_initializer;
1045template <
typename TAllMessages,
typename THandler>
1046typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Registry
1047DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_registry;
1049template <
typename TAllMessages,
typename THandler>
1050typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Initializer
1051DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_initializer(s_registry);
1053template <
typename TAllMessages,
typename THandler>
1054class DispatchMsgTypeBinSearchStrongPolymorphicHelper :
public
1055 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1057 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1058 using Registry =
typename Base::Registry;
1060 using MsgIdParamType =
typename Base::MsgIdParamType;
1061 static bool dispatch(MsgIdParamType
id, THandler& handler)
1064 static_cast<void>(Base::s_initializer);
1068 Base::s_registry.begin(), Base::s_registry.end(),
id,
1069 [](
typename Registry::value_type method, MsgIdParamType idParam) ->
bool
1072 return method->getId() < idParam;
1075 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
1079 (*iter)->dispatch(handler);
1084template <
typename TAllMessages,
typename THandler>
1085class DispatchMsgTypeBinSearchWeakPolymorphicHelper :
public
1086 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1088 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1089 using Registry =
typename Base::Registry;
1092 using MsgIdParamType =
typename Base::MsgIdParamType;
1093 static bool dispatch(MsgIdParamType
id, std::size_t offset, THandler& handler)
1096 static_cast<void>(Base::s_initializer);
1098 using IdType =
typename std::decay<
decltype(id)>::type;
1101 Base::s_registry.begin(), Base::s_registry.end(),
id,
1102 [](
typename Registry::value_type method, IdType idParam) ->
bool
1105 return static_cast<IdType
>(method->getId()) < idParam;
1108 if ((lowerIter == Base::s_registry.end()) ||
1109 (
static_cast<IdType
>((*lowerIter)->getId()) != id)) {
1115 lowerIter, Base::s_registry.end(),
id,
1116 [](IdType idParam,
typename Registry::value_type method)
1118 return idParam < static_cast<IdType>(method->getId());
1124 auto dist =
static_cast<std::size_t
>(upperIter - lowerIter);
1125 if (dist <= offset) {
1129 auto actualIter = lowerIter + offset;
1130 (*actualIter)->dispatch(handler);
1135template <
typename...>
1136class DispatchMsgTypePolymorphicHelper
1138 template <
typename... TParams>
1139 using EmptyTag = comms::details::tag::Tag1<>;
1141 template <
typename... TParams>
1142 using DirectTag = comms::details::tag::Tag2<>;
1144 template <
typename... TParams>
1145 using StrongBinSearchTag = comms::details::tag::Tag3<>;
1147 template <
typename... TParams>
1148 using WeakBinSearchTag = comms::details::tag::Tag4<>;
1150 template <
typename TAllMessages,
typename...>
1151 using DirectStrongTag =
1152 typename comms::util::LazyShallowConditional<
1153 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
1159 template <
typename TAllMessages,
typename...>
1160 using DirectStrongWeakTag =
1161 typename comms::util::LazyShallowConditional<
1162 allMessagesAreStrongSorted<TAllMessages>()
1169 template <
typename TAllMessages,
typename...>
1171 typename comms::util::LazyShallowConditional<
1172 std::tuple_size<TAllMessages>::value == 0U
1175 DirectStrongWeakTag,
1180 template <
typename TAllMessages,
typename TId,
typename THandler>
1181 static bool dispatch(TId&&
id, THandler& handler)
1183 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1184 "Message types must be sorted by their ID");
1186 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, Tag<TAllMessages>());
1189 template <
typename TAllMessages,
typename TId,
typename THandler>
1190 static bool dispatch(TId&&
id, std::size_t offset, THandler& handler)
1192 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1193 "Message types must be sorted by their ID");
1195 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), offset, handler, Tag<TAllMessages>());
1200 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1201 static bool dispatchInternal(TId&&
id, THandler& handler, EmptyTag<TParams...>)
1203 static_cast<void>(id);
1204 static_cast<void>(handler);
1208 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1209 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, EmptyTag<TParams...>)
1211 static_cast<void>(id);
1212 static_cast<void>(handler);
1213 static_cast<void>(offset);
1217 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1218 static bool dispatchInternal(TId&&
id, THandler& handler, DirectTag<TParams...>)
1220 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1221 static_assert(comms::isMessage<FirstMsgType>(),
1222 "The type in the tuple are expected to be proper messages");
1223 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1224 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1225 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1226 return DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, HandlerType>::
1227 dispatch(
static_cast<MsgIdParamType
>(
id), handler);
1230 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1231 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, DirectTag<TParams...>)
1237 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, DirectTag<>());
1240 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1241 static bool dispatchInternal(TId&&
id, THandler& handler, StrongBinSearchTag<TParams...>)
1243 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1244 static_assert(comms::isMessage<FirstMsgType>(),
1245 "The type in the tuple are expected to be proper messages");
1246 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1247 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1248 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1249 return DispatchMsgTypeBinSearchStrongPolymorphicHelper<TAllMessages, HandlerType>::
1250 dispatch(
static_cast<MsgIdParamType
>(
id), handler);
1253 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1254 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, StrongBinSearchTag<TParams...>)
1260 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, StrongBinSearchTag<>());
1263 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1264 static bool dispatchInternal(TId&&
id, THandler& handler, WeakBinSearchTag<TParams...>)
1266 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), 0U, handler, WeakBinSearchTag<>());
1269 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1270 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, WeakBinSearchTag<TParams...>)
1272 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1273 static_assert(comms::isMessage<FirstMsgType>(),
1274 "The type in the tuple are expected to be proper messages");
1275 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1276 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1277 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1278 return DispatchMsgTypeBinSearchWeakPolymorphicHelper<TAllMessages, HandlerType>::
1279 dispatch(
static_cast<MsgIdParamType
>(
id), offset, handler);
This file contains classes required for generic custom assertion functionality.
#define COMMS_ASSERT(expr)
Generic assert macro.
Definition Assert.h:170
Contains various compiler related definitions.
Provides common base class for the custom messages with default implementation.
Contains definition of Message object interface and various base classes for custom messages.
Contains various tuple type manipulation classes and functions.
comms::option::def::MsgType< TMsg > MsgType
Same as comms::option::def::MsgType.
Definition options.h:1500
comms::option::def::MsgIdType< T > MsgIdType
Same as comms::option::def::MsgIdType.
Definition options.h:1486
Main namespace for all classes / functions of COMMS library.
Replacement to some types from standard type_traits.