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;
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>;
155template <
typename TMsgBase,
typename THandler>
156class PolymorphicDirectDispatchRegistryFiller
159 using DispatchMethod = PolymorphicDirectDispatchMethod<TMsgBase, THandler>;
160 PolymorphicDirectDispatchRegistryFiller(
const DispatchMethod** registry)
161 : m_registry(registry)
165 template <
typename TMessage>
168 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
169 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
170 static const PolymorphicDirectDispatchMethodImpl<TMsgBase, THandler, TMessage> Method{};
171 m_registry[
static_cast<std::size_t
>(TMessage::doGetId())] = &Method;
174 const DispatchMethod** m_registry;
177template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
178PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>
179polymorphicDirectDispatchMakeRegistryFiller(
180 PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
182 return PolymorphicDirectDispatchRegistryFiller<TMsgBase, THandler>(®istry[0]);
185template <
typename TRegistry,
typename TAllMessages>
186class PolymorphicDirectDispatchRegistryInitializer
189 PolymorphicDirectDispatchRegistryInitializer() =
delete;
190 PolymorphicDirectDispatchRegistryInitializer(
const PolymorphicDirectDispatchRegistryInitializer&) =
delete;
191 explicit PolymorphicDirectDispatchRegistryInitializer(TRegistry& registry)
193 std::fill(registry.begin(), registry.end(),
nullptr);
194 comms::util::tupleForEachType<TAllMessages>(polymorphicDirectDispatchMakeRegistryFiller(registry));
198template <
typename TMsgBase,
typename THandler>
199class PolymorphicBinSearchDispatchRegistryFiller
202 using DispatchMethod = PolymorphicBinSearchDispatchMethod<TMsgBase, THandler>;
203 PolymorphicBinSearchDispatchRegistryFiller(
const DispatchMethod** registry)
204 : m_registry(registry)
208 template <
typename TMessage>
211 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
212 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
213 static const PolymorphicBinSearchDispatchMethodImpl<TMsgBase, THandler, TMessage> Method{};
214 m_registry[m_idx] = &Method;
219 const DispatchMethod** m_registry;
220 std::size_t m_idx = 0U;
223template <
typename TMsgBase,
typename THandler, std::
size_t TSize>
224PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>
225polymorphicBinSearchDispatchMakeRegistryFiller(
226 PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, TSize>& registry)
228 return PolymorphicBinSearchDispatchRegistryFiller<TMsgBase, THandler>(®istry[0]);
231template <
typename TRegistry,
typename TAllMessages>
232class PolymorphicBinSearchDispatchRegistryInitializer
235 explicit PolymorphicBinSearchDispatchRegistryInitializer(TRegistry& registry)
237 std::fill(registry.begin(), registry.end(),
nullptr);
238 comms::util::tupleForEachType<TAllMessages>(polymorphicBinSearchDispatchMakeRegistryFiller(registry));
242template <
typename TAllMessages, std::
size_t TMaxSize>
243class PolymorphicDirectDispatchRegSizeDetect
245 using MsgType =
typename std::tuple_element<TMaxSize - 1, TAllMessages>::type;
246 static_assert(comms::isMessageBase<MsgType>(),
"Must be actual message");
247 static_assert(messageHasStaticNumId<MsgType>(),
"Message must define static numeric ID");
248 static_assert(MsgType::hasMsgIdType(),
"Message interface class must define its id type");
249 static const typename MsgType::MsgIdParamType MsgId = MsgType::doGetId();
251 static const std::size_t Value =
static_cast<std::size_t
>(MsgId) + 1U;
254template <
typename TAllMessages>
255class PolymorphicDirectDispatchRegSizeDetect<TAllMessages, 0U>
258 static const std::size_t Value = 0;
261template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
262class DispatchMsgDirectPolymorphicHelper
265 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
266 using MsgIdParamType =
typename TMsgBase::MsgIdParamType;
267 static auto dispatch(MsgIdParamType
id, TMsgBase& msg, THandler& handler) ->
268 MessageInterfaceDispatchRetType<
269 typename std::decay<
decltype(handler)>::type>
272 static_cast<void>(s_initializer);
275 MessageInterfaceDispatchRetType<
276 typename std::decay<
decltype(handler)>::type>;
278 auto regIdx =
static_cast<std::size_t
>(id);
279 if ((s_registry.size() <= regIdx) ||
280 (s_registry[regIdx] ==
nullptr)) {
281 return static_cast<RetType
>(handler.handle(msg));
284 return static_cast<RetType
>(s_registry[regIdx]->dispatch(msg, handler));
288 static const std::size_t RegistrySize =
289 PolymorphicDirectDispatchRegSizeDetect<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
290 using Registry = PolymorphicDirectDispatchMsgRegistry<TMsgBase, THandler, RegistrySize>;
291 using Initializer = PolymorphicDirectDispatchRegistryInitializer<Registry, TAllMessages>;
293 static Registry s_registry;
294 static const Initializer s_initializer;
297template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
298typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Registry
299DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_registry;
301template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
302const typename DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::Initializer
303DispatchMsgDirectPolymorphicHelper<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
305template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
306class DispatchMsgBinSearchPolymorphicHelperBase
309 static const std::size_t RegistrySize = std::tuple_size<TAllMessages>::value;
310 using Registry = PolymorphicBinSearchDispatchMsgRegistry<TMsgBase, THandler, RegistrySize>;
311 using Initializer = PolymorphicBinSearchDispatchRegistryInitializer<Registry, TAllMessages>;
313 static Registry s_registry;
314 static Initializer s_initializer;
317template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
318typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Registry
319DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_registry;
321template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
322typename DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::Initializer
323DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>::s_initializer(s_registry);
325template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
326class DispatchMsgBinSearchStrongPolymorphicHelper :
public
327 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
329 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
330 using Registry =
typename Base::Registry;
332 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
333 using MsgIdParamType =
typename TMsgBase::MsgIdParamType;
334 static auto dispatch(MsgIdParamType
id, TMsgBase& msg, THandler& handler) ->
335 MessageInterfaceDispatchRetType<
336 typename std::decay<
decltype(handler)>::type>
339 static_cast<void>(Base::s_initializer);
342 MessageInterfaceDispatchRetType<
343 typename std::decay<
decltype(handler)>::type>;
347 Base::s_registry.begin(), Base::s_registry.end(),
id,
348 [](
typename Registry::value_type method, MsgIdParamType idParam) ->
bool
351 return method->getId() < idParam;
354 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
355 return static_cast<RetType
>(handler.handle(msg));
358 return static_cast<RetType
>((*iter)->dispatch(msg, handler));
362template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
363class DispatchMsgBinSearchWeakPolymorphicHelper :
public
364 DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>
366 using Base = DispatchMsgBinSearchPolymorphicHelperBase<TAllMessages, TMsgBase, THandler>;
367 using Registry =
typename Base::Registry;
369 template <
typename TId>
370 static auto dispatch(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler) ->
371 MessageInterfaceDispatchRetType<
372 typename std::decay<
decltype(handler)>::type>
375 static_cast<void>(Base::s_initializer);
378 MessageInterfaceDispatchRetType<
379 typename std::decay<
decltype(handler)>::type>;
381 using IdType =
typename std::decay<
decltype(id)>::type;
385 Base::s_registry.begin(), Base::s_registry.end(),
id,
386 [](
typename Registry::value_type method, IdType idParam) ->
bool
389 return static_cast<IdType
>(method->getId()) < idParam;
392 if ((lowerIter == Base::s_registry.end()) ||
393 (
static_cast<IdType
>((*lowerIter)->getId()) != id)) {
394 return static_cast<RetType
>(handler.handle(msg));
399 lowerIter, Base::s_registry.end(),
id,
400 [](IdType idParam,
typename Registry::value_type method)
402 return idParam < static_cast<IdType>(method->getId());
408 auto dist =
static_cast<std::size_t
>(upperIter - lowerIter);
409 if (dist <= offset) {
410 return static_cast<RetType
>(handler.handle(msg));
413 auto actualIter = lowerIter + offset;
414 return static_cast<RetType
>((*actualIter)->dispatch(msg, handler));
418template <
typename TElem,
bool TIsMessage>
419struct DispatchMsgPolymorphicLastIdRetriever;
421template <
typename TElem>
422struct DispatchMsgPolymorphicLastIdRetriever<TElem, true>
424 static_assert(messageHasStaticNumId<TElem>(),
"TElem must define static numeric id");
425 static const std::size_t Value =
426 static_cast<std::size_t
>(TElem::doGetId());
429template <
typename TElem>
430struct DispatchMsgPolymorphicLastIdRetriever<TElem, false>
432 static const std::size_t Value = std::numeric_limits<std::size_t>::max();
435template <
typename TAllMessages, std::
size_t TCount>
436class DispatchMsgPolymorphicIsDirectSuitable
439 typename std::tuple_element<
440 std::tuple_size<TAllMessages>::value - 1,
444 static const std::size_t MaxId =
445 DispatchMsgPolymorphicLastIdRetriever<LastMsg, comms::isMessageBase<LastMsg>()>::Value;
447 static const std::size_t MaxAllowedId = (TCount * 11) / 10;
450 static const bool Value =
451 (MaxId <= (TCount + 10U)) || (MaxId <= MaxAllowedId);
454template <
typename TAllMessages>
455class DispatchMsgPolymorphicIsDirectSuitable<TAllMessages, 0U>
458 static const bool Value =
true;
461template <
typename TAllMessages>
462static constexpr bool dispatchMsgPolymorphicIsDirectSuitable()
465 allMessagesHaveStaticNumId<TAllMessages>() &&
466 DispatchMsgPolymorphicIsDirectSuitable<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
469template <
typename...>
470struct DispatchMsgPolymorphicCompatibleHandlerDetector
472 template <
typename TMsg,
typename THandler>
473 using Type = std::is_base_of<typename TMsg::Handler, THandler>;
476template <
typename TMsg,
typename THandler>
477using DispatchMsgPolymorphicCompatibleHandlerDetectBoolType =
478 typename comms::util::LazyDeepConditional<
481 DispatchMsgPolymorphicCompatibleHandlerDetector,
482 comms::util::FalseType,
486template <
typename TMsg,
typename THandler>
487constexpr bool dispatchMsgPolymorphicIsCompatibleHandler()
489 return DispatchMsgPolymorphicCompatibleHandlerDetectBoolType<TMsg, THandler>::value;
492template <
typename ...>
493class DispatchMsgPolymorphicHelper
495 template <
typename... TParams>
496 using EmptyTag = comms::details::tag::Tag1<>;
498 template <
typename... TParams>
499 using DispatchInterfaceTag = comms::details::tag::Tag2<>;
501 template <
typename... TParams>
502 using DirectTag = comms::details::tag::Tag3<>;
504 template <
typename... TParams>
505 using StrongBinSearchTag = comms::details::tag::Tag4<>;
507 template <
typename... TParams>
508 using WeakBinSearchTag = comms::details::tag::Tag5<>;
510 template <
typename... TParams>
511 using IdInterfaceTag = comms::details::tag::Tag6<>;
513 template <
typename... TParams>
514 using NoIdInterfaceTag = comms::details::tag::Tag7<>;
516 template <
typename TAllMessages,
typename...>
517 using DirectStrongTag =
518 typename comms::util::LazyShallowConditional<
519 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
525 template <
typename TAllMessages,
typename...>
526 using DirectStrongWeakTag =
527 typename comms::util::LazyShallowConditional<
528 allMessagesAreStrongSorted<TAllMessages>()
535 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename...>
537 typename comms::util::LazyShallowConditional<
538 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
540 DispatchInterfaceTag,
545 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename...>
547 typename comms::util::LazyShallowConditional<
548 comms::isMessageBase<TMsgBase>()
552 TAllMessages, TMsgBase, THandler
555 template <
typename TMsgBase,
typename...>
556 using InterfaceDispatchTag =
557 typename comms::util::LazyShallowConditional<
564 template <
typename TMsgBase,
typename THandler,
typename...>
565 using PolymorphicCheckDispatchTag =
566 typename comms::util::LazyShallowConditional<
567 dispatchMsgPolymorphicIsCompatibleHandler<TMsgBase, THandler>()
570 InterfaceDispatchTag,
575 template <
typename TAllMessages,
typename TMsgBase,
typename THandler>
576 static auto dispatch(TMsgBase& msg, THandler& handler) ->
577 MessageInterfaceDispatchRetType<
578 typename std::decay<
decltype(handler)>::type>
581 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
582 "Message types must be sorted by their ID");
584 static_assert(comms::isMessage<TMsgBase>(),
585 "TMsgBase is expected to be message interface class");
587 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
589 using MsgType =
typename std::decay<
decltype(msg)>::type;
590 using HandlerType =
typename std::decay<
decltype(handler)>::type;
591 using IdRetrieveTag =
592 typename comms::util::LazyShallowConditional<
593 comms::isMessageBase<MsgType>()
596 PolymorphicCheckDispatchTag,
600 return dispatchInternal<TAllMessages>(msg, handler, IdRetrieveTag());
603 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler>
604 static auto dispatch(TId&&
id, TMsgBase& msg, THandler& handler) ->
605 MessageInterfaceDispatchRetType<
606 typename std::decay<
decltype(handler)>::type>
608 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
609 "Message types must be sorted by their ID");
611 static_assert(comms::isMessage<TMsgBase>(),
612 "TMsgBase is expected to be message interface class");
614 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
616 using MsgType =
typename std::decay<
decltype(msg)>::type;
617 using HandlerType =
typename std::decay<
decltype(handler)>::type;
619 dispatchInternal<TAllMessages>(
620 static_cast<typename MsgType::MsgIdParamType
>(
id),
623 AdjustedTag<TAllMessages, MsgType, HandlerType>());
626 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler>
627 static auto dispatch(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler) ->
628 MessageInterfaceDispatchRetType<
629 typename std::decay<
decltype(handler)>::type>
631 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
632 "Message types must be sorted by their ID");
634 static_assert(comms::isMessage<TMsgBase>(),
635 "TMsgBase is expected to be message interface class");
637 static_assert(TMsgBase::hasMsgIdType(),
"Message interface class must define its id type");
639 using MsgType =
typename std::decay<
decltype(msg)>::type;
640 using HandlerType =
typename std::decay<
decltype(handler)>::type;
642 dispatchInternal<TAllMessages>(
643 static_cast<typename MsgType::MsgIdParamType
>(
id),
647 AdjustedTag<TAllMessages, MsgType, HandlerType>());
651 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
652 static auto dispatchInternal(TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
653 decltype(handler.handle(msg))
655 return handler.handle(msg);
658 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
659 static auto dispatchInternal(TMsgBase& msg, THandler& handler, IdInterfaceTag<TParams...>) ->
660 MessageInterfaceDispatchRetType<
661 typename std::decay<
decltype(handler)>::type>
663 typename TMsgBase::MsgIdParamType
id = msg.getId();
664 return dispatch<TAllMessages>(
id, msg, handler);
667 template <
typename TAllMessages,
typename TMsgBase,
typename THandler,
typename... TParams>
668 static auto dispatchInternal(TMsgBase& msg, THandler& handler, NoIdInterfaceTag<TParams...>) ->
669 MessageInterfaceDispatchRetType<
670 typename std::decay<
decltype(handler)>::type>
672 static_assert(TMsgBase::hasDispatch(),
"The message must provide polymorphic dispatch");
673 static_assert(std::is_base_of<typename TMsgBase::Handler, THandler>::value,
674 "Incompatible handlers");
676 using RetType = MessageInterfaceDispatchRetType<THandler>;
677 return static_cast<RetType
>(msg.dispatch(handler));
680 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
681 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
682 decltype(handler.handle(msg))
684 static_cast<void>(id);
685 return handler.handle(msg);
688 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
689 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, DispatchInterfaceTag<TParams...>) ->
690 MessageInterfaceDispatchRetType<
691 typename std::decay<
decltype(handler)>::type>
693 static_cast<void>(id);
694 return dispatchInternal<TAllMessages>(msg, handler, NoIdInterfaceTag<>());
697 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
698 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, DirectTag<TParams...>) ->
699 MessageInterfaceDispatchRetType<
700 typename std::decay<
decltype(handler)>::type>
702 using MsgType =
typename std::decay<
decltype(msg)>::type;
703 using HandlerType =
typename std::decay<
decltype(handler)>::type;
705 return DispatchMsgDirectPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
706 dispatch(std::forward<TId>(
id), msg, handler);
709 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
710 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, StrongBinSearchTag<TParams...>) ->
711 MessageInterfaceDispatchRetType<
712 typename std::decay<
decltype(handler)>::type>
714 using MsgType =
typename std::decay<
decltype(msg)>::type;
715 using HandlerType =
typename std::decay<
decltype(handler)>::type;
717 return DispatchMsgBinSearchStrongPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
718 dispatch(std::forward<TId>(
id), msg, handler);
721 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
722 static auto dispatchInternal(TId&&
id, TMsgBase& msg, THandler& handler, WeakBinSearchTag<TParams...>) ->
723 MessageInterfaceDispatchRetType<
724 typename std::decay<
decltype(handler)>::type>
726 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), 0U, msg, handler, WeakBinSearchTag<>());
729 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
730 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, DispatchInterfaceTag<TParams...>) ->
731 MessageInterfaceDispatchRetType<
732 typename std::decay<
decltype(handler)>::type>
734 static_cast<void>(id);
735 static_cast<void>(offset);
736 static_assert(std::is_base_of<typename TMsgBase::Handler, THandler>::value,
737 "Incompatible handlers");
739 using RetType = MessageInterfaceDispatchRetType<THandler>;
740 return static_cast<RetType
>(msg.dispatch(handler));
743 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
744 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, EmptyTag<TParams...>) ->
745 decltype(handler.handle(msg))
747 static_cast<void>(id);
748 static_cast<void>(offset);
749 return handler.handle(msg);
752 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
753 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, DirectTag<TParams...>) ->
754 MessageInterfaceDispatchRetType<
755 typename std::decay<
decltype(handler)>::type>
758 using RetType = MessageInterfaceDispatchRetType<THandler>;
759 return static_cast<RetType
>(handler.handle(msg));
762 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), msg, handler, DirectTag<>());
765 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
766 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, StrongBinSearchTag<TParams...>) ->
767 MessageInterfaceDispatchRetType<
768 typename std::decay<
decltype(handler)>::type>
771 using RetType = MessageInterfaceDispatchRetType<THandler>;
772 return static_cast<RetType
>(handler.handle(msg));
775 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), msg, handler, StrongBinSearchTag<>());
778 template <
typename TAllMessages,
typename TId,
typename TMsgBase,
typename THandler,
typename... TParams>
779 static auto dispatchInternal(TId&&
id, std::size_t offset, TMsgBase& msg, THandler& handler, WeakBinSearchTag<TParams...>) ->
780 MessageInterfaceDispatchRetType<
781 typename std::decay<
decltype(handler)>::type>
783 using MsgType =
typename std::decay<
decltype(msg)>::type;
784 using HandlerType =
typename std::decay<
decltype(handler)>::type;
786 return DispatchMsgBinSearchWeakPolymorphicHelper<TAllMessages, MsgType, HandlerType>::
787 dispatch(std::forward<TId>(
id), offset, msg, handler);
793template <
typename THandler>
794class PolymorphicTypeDirectDispatchMethod
797 PolymorphicTypeDirectDispatchMethod(
const PolymorphicTypeDirectDispatchMethod&) =
delete;
798 PolymorphicTypeDirectDispatchMethod& operator=(
const PolymorphicTypeDirectDispatchMethod&) =
delete;
800 virtual void dispatch(THandler& handler)
const
802 dispatchImpl(handler);
806 PolymorphicTypeDirectDispatchMethod() =
default;
807 ~PolymorphicTypeDirectDispatchMethod() =
default;
809 virtual void dispatchImpl(THandler& handler)
const = 0;
812template <
typename THandler,
typename TMessage>
813class PolymorphicTypeDirectDispatchMethodImpl :
public
814 PolymorphicTypeDirectDispatchMethod<THandler>
817 PolymorphicTypeDirectDispatchMethodImpl() =
default;
818 PolymorphicTypeDirectDispatchMethodImpl(
const PolymorphicTypeDirectDispatchMethodImpl&) =
delete;
819 PolymorphicTypeDirectDispatchMethodImpl& operator=(
const PolymorphicTypeDirectDispatchMethodImpl&) =
delete;
822 virtual void dispatchImpl(THandler& handler)
const
823#ifndef COMMS_COMPILER_GCC47
827 return handler.template handle<TMessage>();
831template <
typename TMsgIdType,
typename THandler>
832class PolymorphicTypeBinSearchDispatchMethod
835 PolymorphicTypeBinSearchDispatchMethod(
const PolymorphicTypeBinSearchDispatchMethod&) =
delete;
836 PolymorphicTypeBinSearchDispatchMethod& operator=(
const PolymorphicTypeBinSearchDispatchMethod&) =
delete;
838 virtual TMsgIdType getId()
const
843 virtual void dispatch(THandler& handler)
const
845 return dispatchImpl(handler);
849 PolymorphicTypeBinSearchDispatchMethod() =
default;
850 ~PolymorphicTypeBinSearchDispatchMethod() =
default;
852 virtual TMsgIdType getIdImpl()
const = 0;
853 virtual void dispatchImpl(THandler& handler)
const = 0;
856template <
typename TMsgIdType,
typename THandler,
typename TMessage>
857class PolymorphicTypeBinSearchDispatchMethodImpl :
public
858 PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>
860 using Base = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
862 PolymorphicTypeBinSearchDispatchMethodImpl() =
default;
863 PolymorphicTypeBinSearchDispatchMethodImpl(
const PolymorphicTypeBinSearchDispatchMethodImpl&) =
delete;
864 PolymorphicTypeBinSearchDispatchMethodImpl& operator=(
const PolymorphicTypeBinSearchDispatchMethodImpl&) =
delete;
866 static TMsgIdType doGetId()
868 return dispatchMsgGetMsgId<TMessage>();
872 virtual TMsgIdType getIdImpl() const
873#ifndef COMMS_COMPILER_GCC47
880 virtual void dispatchImpl(THandler& handler)
const
881#ifndef COMMS_COMPILER_GCC47
885 return handler.template handle<TMessage>();
889template <
typename THandler, std::
size_t TSize>
890using PolymorphicTypeDirectDispatchMsgRegistry =
891 std::array<const PolymorphicTypeDirectDispatchMethod<THandler>*, TSize>;
893template <
typename TMsgIdType,
typename THandler, std::
size_t TSize>
894using PolymorphicTypeBinSearchDispatchMsgRegistry =
895 std::array<const PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>*, TSize>;
897template <
typename THandler>
898class PolymorphicTypeDirectDispatchRegistryFiller
901 using DispatchMethod = PolymorphicTypeDirectDispatchMethod<THandler>;
902 PolymorphicTypeDirectDispatchRegistryFiller(
const DispatchMethod** registry)
903 : m_registry(registry)
907 template <
typename TMessage>
910 static_assert(comms::isMessageBase<TMessage>(),
"Must be actual message");
911 static_assert(messageHasStaticNumId<TMessage>(),
"Message must define static ID");
912 static const PolymorphicTypeDirectDispatchMethodImpl<THandler, TMessage> Method{};
913 m_registry[
static_cast<std::size_t
>(TMessage::doGetId())] = &Method;
916 const DispatchMethod** m_registry;
919template <
typename THandler, std::
size_t TSize>
920PolymorphicTypeDirectDispatchRegistryFiller<THandler>
921polymorphicTypeDirectDispatchMakeRegistryFiller(
922 PolymorphicTypeDirectDispatchMsgRegistry<THandler, TSize>& registry)
924 return PolymorphicTypeDirectDispatchRegistryFiller<THandler>(®istry[0]);
927template <
typename TRegistry,
typename TAllMessages>
928class PolymorphicTypeDirectDispatchRegistryInitializer
931 PolymorphicTypeDirectDispatchRegistryInitializer() =
delete;
932 PolymorphicTypeDirectDispatchRegistryInitializer(
const PolymorphicTypeDirectDispatchRegistryInitializer&) =
delete;
933 explicit PolymorphicTypeDirectDispatchRegistryInitializer(TRegistry& registry)
935 std::fill(registry.begin(), registry.end(),
nullptr);
936 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeDirectDispatchMakeRegistryFiller(registry));
940template <
typename TMsgIdType,
typename THandler>
941class PolymorphicTypeBinSearchDispatchRegistryFiller
944 using DispatchMethod = PolymorphicTypeBinSearchDispatchMethod<TMsgIdType, THandler>;
945 PolymorphicTypeBinSearchDispatchRegistryFiller(
const DispatchMethod** registry)
946 : m_registry(registry)
950 template <
typename TMessage>
955 static const PolymorphicTypeBinSearchDispatchMethodImpl<TMsgIdType, THandler, TMessage> Method{};
956 m_registry[m_idx] = &Method;
961 const DispatchMethod** m_registry;
962 std::size_t m_idx = 0U;
965template <
typename TMsgIdType,
typename THandler, std::
size_t TSize>
966PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>
967polymorphicTypeBinSearchDispatchMakeRegistryFiller(
968 PolymorphicTypeBinSearchDispatchMsgRegistry<TMsgIdType, THandler, TSize>& registry)
970 return PolymorphicTypeBinSearchDispatchRegistryFiller<TMsgIdType, THandler>(®istry[0]);
973template <
typename TRegistry,
typename TAllMessages>
974class PolymorphicTypeBinSearchDispatchRegistryInitializer
977 explicit PolymorphicTypeBinSearchDispatchRegistryInitializer(TRegistry& registry)
979 std::fill(registry.begin(), registry.end(),
nullptr);
980 comms::util::tupleForEachType<TAllMessages>(polymorphicTypeBinSearchDispatchMakeRegistryFiller(registry));
984template <
typename TAllMessages,
typename THandler>
985class DispatchMsgTypeDirectPolymorphicHelper
988 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
989 static_assert(FirstMsgType::hasMsgIdType(),
"Message interface class must define its id type");
990 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
991 static bool dispatch(MsgIdParamType
id, THandler& handler)
994 static_cast<void>(s_initializer);
996 auto regIdx =
static_cast<std::size_t
>(id);
997 if ((s_registry.size() <= regIdx) ||
998 (s_registry[regIdx] ==
nullptr)) {
1002 s_registry[regIdx]->dispatch(handler);
1007 static const std::size_t RegistrySize =
1008 PolymorphicDirectDispatchRegSizeDetect<TAllMessages, std::tuple_size<TAllMessages>::value>::Value;
1009 using Registry = PolymorphicTypeDirectDispatchMsgRegistry<THandler, RegistrySize>;
1010 using Initializer = PolymorphicTypeDirectDispatchRegistryInitializer<Registry, TAllMessages>;
1012 static Registry s_registry;
1013 static const Initializer s_initializer;
1016template <
typename TAllMessages,
typename THandler>
1017typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Registry
1018DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_registry;
1020template <
typename TAllMessages,
typename THandler>
1021const typename DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::Initializer
1022DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, THandler>::s_initializer(s_registry);
1024template <
typename TAllMessages,
typename THandler>
1025class DispatchMsgTypeBinSearchPolymorphicHelperBase
1028 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1029 static_assert(comms::isMessage<FirstMsgType>(),
1030 "The type in the tuple are expected to be proper messages");
1031 static_assert(FirstMsgType::hasMsgIdType(),
"Message interface class must define its id type");
1032 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1034 static const std::size_t RegistrySize = std::tuple_size<TAllMessages>::value;
1035 using Registry = PolymorphicTypeBinSearchDispatchMsgRegistry<MsgIdParamType, THandler, RegistrySize>;
1036 using Initializer = PolymorphicTypeBinSearchDispatchRegistryInitializer<Registry, TAllMessages>;
1038 static Registry s_registry;
1039 static Initializer s_initializer;
1042template <
typename TAllMessages,
typename THandler>
1043typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Registry
1044DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_registry;
1046template <
typename TAllMessages,
typename THandler>
1047typename DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::Initializer
1048DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>::s_initializer(s_registry);
1050template <
typename TAllMessages,
typename THandler>
1051class DispatchMsgTypeBinSearchStrongPolymorphicHelper :
public
1052 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1054 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1055 using Registry =
typename Base::Registry;
1057 using MsgIdParamType =
typename Base::MsgIdParamType;
1058 static bool dispatch(MsgIdParamType
id, THandler& handler)
1061 static_cast<void>(Base::s_initializer);
1065 Base::s_registry.begin(), Base::s_registry.end(),
id,
1066 [](
typename Registry::value_type method, MsgIdParamType idParam) ->
bool
1069 return method->getId() < idParam;
1072 if ((iter == Base::s_registry.end()) || ((*iter)->getId() != id)) {
1076 (*iter)->dispatch(handler);
1081template <
typename TAllMessages,
typename THandler>
1082class DispatchMsgTypeBinSearchWeakPolymorphicHelper :
public
1083 DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>
1085 using Base = DispatchMsgTypeBinSearchPolymorphicHelperBase<TAllMessages, THandler>;
1086 using Registry =
typename Base::Registry;
1089 using MsgIdParamType =
typename Base::MsgIdParamType;
1090 static bool dispatch(MsgIdParamType
id, std::size_t offset, THandler& handler)
1093 static_cast<void>(Base::s_initializer);
1095 using IdType =
typename std::decay<
decltype(id)>::type;
1098 Base::s_registry.begin(), Base::s_registry.end(),
id,
1099 [](
typename Registry::value_type method, IdType idParam) ->
bool
1102 return static_cast<IdType
>(method->getId()) < idParam;
1105 if ((lowerIter == Base::s_registry.end()) ||
1106 (
static_cast<IdType
>((*lowerIter)->getId()) != id)) {
1112 lowerIter, Base::s_registry.end(),
id,
1113 [](IdType idParam,
typename Registry::value_type method)
1115 return idParam < static_cast<IdType>(method->getId());
1121 auto dist =
static_cast<std::size_t
>(upperIter - lowerIter);
1122 if (dist <= offset) {
1126 auto actualIter = lowerIter + offset;
1127 (*actualIter)->dispatch(handler);
1132template <
typename...>
1133class DispatchMsgTypePolymorphicHelper
1135 template <
typename... TParams>
1136 using EmptyTag = comms::details::tag::Tag1<>;
1138 template <
typename... TParams>
1139 using DirectTag = comms::details::tag::Tag2<>;
1141 template <
typename... TParams>
1142 using StrongBinSearchTag = comms::details::tag::Tag3<>;
1144 template <
typename... TParams>
1145 using WeakBinSearchTag = comms::details::tag::Tag4<>;
1147 template <
typename TAllMessages,
typename...>
1148 using DirectStrongTag =
1149 typename comms::util::LazyShallowConditional<
1150 dispatchMsgPolymorphicIsDirectSuitable<TAllMessages>()
1156 template <
typename TAllMessages,
typename...>
1157 using DirectStrongWeakTag =
1158 typename comms::util::LazyShallowConditional<
1159 allMessagesAreStrongSorted<TAllMessages>()
1166 template <
typename TAllMessages,
typename...>
1168 typename comms::util::LazyShallowConditional<
1169 std::tuple_size<TAllMessages>::value == 0U
1172 DirectStrongWeakTag,
1177 template <
typename TAllMessages,
typename TId,
typename THandler>
1178 static bool dispatch(TId&&
id, THandler& handler)
1180 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1181 "Message types must be sorted by their ID");
1183 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, Tag<TAllMessages>());
1186 template <
typename TAllMessages,
typename TId,
typename THandler>
1187 static bool dispatch(TId&&
id, std::size_t offset, THandler& handler)
1189 static_assert(allMessagesAreWeakSorted<TAllMessages>() || (!allMessagesHaveStaticNumId<TAllMessages>()),
1190 "Message types must be sorted by their ID");
1192 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), offset, handler, Tag<TAllMessages>());
1197 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1198 static bool dispatchInternal(TId&&
id, THandler& handler, EmptyTag<TParams...>)
1200 static_cast<void>(id);
1201 static_cast<void>(handler);
1205 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1206 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, EmptyTag<TParams...>)
1208 static_cast<void>(id);
1209 static_cast<void>(handler);
1210 static_cast<void>(offset);
1214 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1215 static bool dispatchInternal(TId&&
id, THandler& handler, DirectTag<TParams...>)
1217 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1218 static_assert(comms::isMessage<FirstMsgType>(),
1219 "The type in the tuple are expected to be proper messages");
1220 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1221 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1222 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1223 return DispatchMsgTypeDirectPolymorphicHelper<TAllMessages, HandlerType>::
1224 dispatch(
static_cast<MsgIdParamType
>(
id), handler);
1227 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1228 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, DirectTag<TParams...>)
1234 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, DirectTag<>());
1237 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1238 static bool dispatchInternal(TId&&
id, THandler& handler, StrongBinSearchTag<TParams...>)
1240 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1241 static_assert(comms::isMessage<FirstMsgType>(),
1242 "The type in the tuple are expected to be proper messages");
1243 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1244 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1245 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1246 return DispatchMsgTypeBinSearchStrongPolymorphicHelper<TAllMessages, HandlerType>::
1247 dispatch(
static_cast<MsgIdParamType
>(
id), handler);
1250 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1251 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, StrongBinSearchTag<TParams...>)
1257 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), handler, StrongBinSearchTag<>());
1260 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1261 static bool dispatchInternal(TId&&
id, THandler& handler, WeakBinSearchTag<TParams...>)
1263 return dispatchInternal<TAllMessages>(std::forward<TId>(
id), 0U, handler, WeakBinSearchTag<>());
1266 template <
typename TAllMessages,
typename TId,
typename THandler,
typename... TParams>
1267 static bool dispatchInternal(TId&&
id, std::size_t offset, THandler& handler, WeakBinSearchTag<TParams...>)
1269 using FirstMsgType =
typename std::tuple_element<0, TAllMessages>::type;
1270 static_assert(comms::isMessage<FirstMsgType>(),
1271 "The type in the tuple are expected to be proper messages");
1272 static_assert(FirstMsgType::hasMsgIdType(),
"The messages must define their ID type");
1273 using MsgIdParamType =
typename FirstMsgType::MsgIdParamType;
1274 using HandlerType =
typename std::decay<
decltype(handler)>::type;
1275 return DispatchMsgTypeBinSearchWeakPolymorphicHelper<TAllMessages, HandlerType>::
1276 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:168
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:1498
comms::option::def::MsgIdType< T > MsgIdType
Same as comms::option::def::MsgIdType.
Definition options.h:1484
Main namespace for all classes / functions of COMMS library.
Replacement to some types from standard type_traits.