Embedded Template Library 1.0
Loading...
Searching...
No Matches
message_router.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2017 John Wellbelove
9
10Permission is hereby granted, free of charge, to any person obtaining a copy
11of this software and associated documentation files(the "Software"), to deal
12in the Software without restriction, including without limitation the rights
13to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
14copies of the Software, and to permit persons to whom the Software is
15furnished to do so, subject to the following conditions :
16
17The above copyright notice and this permission notice shall be included in all
18copies or substantial portions of the Software.
19
20THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
23AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26SOFTWARE.
27******************************************************************************/
28
29#ifndef ETL_MESSAGE_ROUTER_INCLUDED
30#define ETL_MESSAGE_ROUTER_INCLUDED
31
32#include "platform.h"
33#include "alignment.h"
34#include "array.h"
35#include "error_handler.h"
36#include "exception.h"
37#include "largest.h"
38#include "message.h"
39#include "message_packet.h"
40#include "message_types.h"
41#include "shared_message.h"
42#include "successor.h"
43#include "type_list.h"
44#include "type_traits.h"
46#include <stddef.h>
47
48namespace etl
49{
50 //***************************************************************************
52 //***************************************************************************
53 class message_router_exception : public etl::exception
54 {
55 public:
56
57 message_router_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
58 : etl::exception(reason_, file_name_, line_number_)
59 {
60 }
61 };
62
63 //***************************************************************************
65 //***************************************************************************
66 class message_router_illegal_id : public etl::message_router_exception
67 {
68 public:
69
70 message_router_illegal_id(string_type file_name_, numeric_type line_number_)
71 : message_router_exception(ETL_ERROR_TEXT("message router:illegal id", ETL_MESSAGE_ROUTER_FILE_ID"A"), file_name_, line_number_)
72 {
73 }
74 };
75
76 namespace private_message_router
77 {
78#if ETL_USING_CPP11
79 //***************************************************************************
80 // Traits for a message router.
81 // message packet type
82 // message type_list
83 // sorted message type_list.
84 //***************************************************************************
85 template <typename... TMessageTypes>
86 class traits
87 {
88 private:
89
90 using message_id_sequence = etl::index_sequence<TMessageTypes::ID...>;
91
92 public:
93
94 using message_packet = etl::message_packet<TMessageTypes...>;
95 using message_types = etl::type_list<TMessageTypes...>;
96 using sorted_message_types = etl::type_list_sort_t<message_types, etl::compare_message_id_less>;
97
98 static_assert(etl::type_list_is_unique<message_types>::value, "All TMessageTypes must be unique");
99 static_assert(etl::type_list_all_of<message_types, etl::is_message_type>::value,
100 "All TMessageTypes must satisfy the condition etl::is_message_type");
101 static_assert(etl::index_sequence_is_unique<message_id_sequence>::value, "All message IDs must be unique");
102 };
103
104 //***************************************************************************
105 // Specialisation of traits for no message types.
106 // message packet type
107 // message type_list
108 // sorted message type_list.
109 //***************************************************************************
110 template <>
111 class traits<>
112 {
113 public:
114
116 using message_types = etl::type_list<>;
117 using sorted_message_types = etl::type_list<>;
118 };
119#else
120 //***************************************************************************
121 // C++03 empty traits placeholder.
122 //***************************************************************************
123 template <typename T1 = void>
124 class traits
125 {
126 };
127#endif
128 } // namespace private_message_router
129
130 //***************************************************************************
132 //***************************************************************************
133 class imessage_router;
134
136
137 //***************************************************************************
139 //***************************************************************************
140 class imessage_router : public etl::successor<imessage_router>
141 {
142 public:
143
144 virtual ~imessage_router() {}
145 virtual void receive(const etl::imessage&) = 0;
146 virtual bool accepts(etl::message_id_t) const = 0;
147 virtual bool is_null_router() const = 0;
148 virtual bool is_producer() const = 0;
149 virtual bool is_consumer() const = 0;
150
151 //********************************************
152 virtual void receive(etl::message_router_id_t destination_router_id, const etl::imessage& message)
153 {
154 if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
155 {
156 receive(message);
157 }
158 }
159
160 //********************************************
161 virtual void receive(etl::shared_message shared_msg)
162 {
163 receive(shared_msg.get_message());
164 }
165
166 //********************************************
167 virtual void receive(etl::message_router_id_t destination_router_id, etl::shared_message shared_msg)
168 {
169 if ((destination_router_id == get_message_router_id()) || (destination_router_id == imessage_router::ALL_MESSAGE_ROUTERS))
170 {
171 receive(shared_msg);
172 }
173 }
174
175 //********************************************
176 bool accepts(const etl::imessage& msg) const
177 {
178 return accepts(msg.get_message_id());
179 }
180
181 //********************************************
182 etl::message_router_id_t get_message_router_id() const
183 {
184 return message_router_id;
185 }
186
187 enum
188 {
189 NULL_MESSAGE_ROUTER = 255,
190 MESSAGE_BUS = 254,
191 ALL_MESSAGE_ROUTERS = 253,
192 MESSAGE_BROKER = 252,
193 MESSAGE_ROUTER = 251,
194 MAX_MESSAGE_ROUTER = 249
195 };
196
197 protected:
199 imessage_router(etl::message_router_id_t id_)
200 : message_router_id(id_)
201 {
202 }
203
204 imessage_router(etl::message_router_id_t id_, imessage_router& successor_)
205 : successor(successor_)
206 , message_router_id(id_)
207 {
208 }
209
210 private:
211
212 // Disabled.
213 imessage_router(const imessage_router&);
214 imessage_router& operator=(const imessage_router&);
215
216 etl::message_router_id_t message_router_id;
217 };
218
219 //***************************************************************************
221 //***************************************************************************
222 class null_message_router
223 : public imessage_router
225 {
226 public:
227
228 //********************************************
229 null_message_router()
230 : imessage_router(imessage_router::NULL_MESSAGE_ROUTER)
231 {
232 }
233
234 //********************************************
235 null_message_router(etl::imessage_router& successor_)
236 : imessage_router(imessage_router::NULL_MESSAGE_ROUTER, successor_)
237 {
238 }
239
240 //********************************************
241 using etl::imessage_router::receive;
242
243 void receive(const etl::imessage& msg) ETL_OVERRIDE
244 {
245 if (has_successor())
246 {
247 get_successor().receive(msg);
248 }
249 }
250
251 //********************************************
252 using etl::imessage_router::accepts;
253
254 bool accepts(etl::message_id_t id) const ETL_OVERRIDE
255 {
256 if (has_successor())
257 {
258 return get_successor().accepts(id);
259 }
260 else
261 {
262 return false;
263 }
264 }
265
266 //********************************************
267 ETL_DEPRECATED
268 bool is_null_router() const ETL_OVERRIDE
269 {
270 return true;
271 }
272
273 //********************************************
274 bool is_producer() const ETL_OVERRIDE
275 {
276 return false;
277 }
278
279 //********************************************
280 bool is_consumer() const ETL_OVERRIDE
281 {
282 return false;
283 }
284
285 //********************************************
286 static null_message_router& instance()
287 {
288 static null_message_router nmr;
289 return nmr;
290 }
291 };
292
293 //***********************************************
296 {
297 return etl::null_message_router::instance();
298 }
299
300 //***************************************************************************
303 //***************************************************************************
304 class message_producer
305 : public imessage_router
307 {
308 public:
309
310 //********************************************
311 message_producer()
312 : imessage_router(etl::imessage_router::MESSAGE_ROUTER)
313 {
314 }
315
316 //********************************************
317 message_producer(etl::imessage_router& successor_)
318 : imessage_router(imessage_router::NULL_MESSAGE_ROUTER, successor_)
319 {
320 }
321
322 //********************************************
323 message_producer(etl::message_router_id_t id_)
324 : imessage_router(id_)
325 {
326 ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
327 }
328
329 //********************************************
330 message_producer(etl::message_router_id_t id_, etl::imessage_router& successor_)
331 : imessage_router(id_, successor_)
332 {
333 ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
334 }
335
336 //********************************************
337 using etl::imessage_router::receive;
338
339 void receive(const etl::imessage& msg) ETL_OVERRIDE
340 {
341 if (has_successor())
342 {
343 get_successor().receive(msg);
344 }
345 }
346
347 //********************************************
348 using etl::imessage_router::accepts;
349
350 bool accepts(etl::message_id_t id) const ETL_OVERRIDE
351 {
352 if (has_successor())
354 return get_successor().accepts(id);
355 }
356 else
357 {
358 return false;
359 }
360 }
361
362 //********************************************
363 ETL_DEPRECATED
364 bool is_null_router() const ETL_OVERRIDE
365 {
366 return false;
367 }
368
369 //********************************************
370 bool is_producer() const ETL_OVERRIDE
371 {
372 return true;
373 }
374
375 //********************************************
376 bool is_consumer() const ETL_OVERRIDE
377 {
378 return false;
379 }
380 };
381
382 //***************************************************************************
384 //***************************************************************************
385 template <typename T>
386 struct is_message_router : public etl::bool_constant< etl::is_base_of< etl::imessage_router, typename etl::remove_cvref<T>::type>::value>
387 {
388 };
389
390 //***************************************************************************
392 //***************************************************************************
393 template <typename TRouter, typename TMessage>
394 static typename etl::enable_if< etl::is_message_router<TRouter>::value && etl::is_message<TMessage>::value, void>::type
395 send_message(TRouter& destination, const TMessage& message)
396 {
397 destination.receive(message);
398 }
399
400 //***************************************************************************
402 //***************************************************************************
403 template <typename TRouter>
404 static typename etl::enable_if<etl::is_message_router<TRouter>::value, void>::type send_message(TRouter& destination, etl::shared_message message)
405 {
406 destination.receive(message);
407 }
408
409 //***************************************************************************
411 //***************************************************************************
412 template <typename TRouter, typename TMessage>
413 static typename etl::enable_if< etl::is_message_router<TRouter>::value && etl::is_message<TMessage>::value, void>::type
414 send_message(TRouter& destination, etl::message_router_id_t id, const TMessage& message)
415 {
416 destination.receive(id, message);
417 }
418
419 //***************************************************************************
421 //***************************************************************************
422 template <typename TRouter>
423 static typename etl::enable_if<etl::is_message_router<TRouter>::value, void>::type send_message(TRouter& destination, etl::message_router_id_t id,
424 etl::shared_message message)
425 {
426 destination.receive(id, message);
427 }
428
429 //*************************************************************************************************
430 // For C++11 and above.
431 //*************************************************************************************************
432#if ETL_USING_CPP11 && !defined(ETL_MESSAGE_ROUTER_FORCE_CPP03_IMPLEMENTATION)
433 //***************************************************************************
434 // The definition for all message types.
435 //***************************************************************************
436 template <typename TDerived, typename... TMessageTypes>
437 class message_router
438 : public imessage_router
439 , public private_message_router::traits<TMessageTypes...>
440 {
441 public:
442
443 using typename private_message_router::traits<TMessageTypes...>::message_packet;
444 using typename private_message_router::traits<TMessageTypes...>::message_types;
445 using typename private_message_router::traits< TMessageTypes...>::sorted_message_types;
446
447 //**********************************************
449 //**********************************************
450 message_router()
451 : imessage_router(etl::imessage_router::MESSAGE_ROUTER)
452 {
453 }
454
455 //**********************************************
458 //**********************************************
459 message_router(etl::imessage_router& successor_)
460 : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
461 {
462 }
463
464 //**********************************************
466 //**********************************************
467 message_router(etl::message_router_id_t id_)
468 : imessage_router(id_)
469 {
470 ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
471 }
472
473 //**********************************************
475 //**********************************************
476 message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
477 : imessage_router(id_, successor_)
478 {
479 ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
480 }
481
482 //**********************************************
484 //**********************************************
485 using etl::imessage_router::receive;
486
487 //**********************************************
492 //***********************************************
493 void receive(const etl::imessage& msg) ETL_OVERRIDE
494 {
495 const etl::message_id_t id = msg.get_message_id();
496
497 // The IDs are sorted, so an ID less than the first is not handled by this
498 // router.
499 if (id >= Message_Id_Start)
500 {
501 const size_t index = get_dispatch_index_from_message_id(id);
502
503 // If the index is less than Number_Of_Messages, then we have a handler
504 // for this message type, so dispatch it.
505 if (index < Number_Of_Messages)
506 {
507 dispatch(msg, index);
508 return;
509 }
510 }
511
512 // We don't have a handler for this message type, so pass it to a
513 // successor if there is one, or call on_receive_unknown() if there isn't.
514 if (has_successor())
515 {
516 get_successor().receive(msg);
517 }
518 else
519 {
521 static_cast<TDerived*>(this)->on_receive_unknown(msg);
523 }
524 }
525
526 //**********************************************
530 //**********************************************
531 template < typename TMessage, typename etl::enable_if<etl::is_one_of<TMessage, TMessageTypes...>::value, int>::type = 0>
532 void receive(const TMessage& msg)
533 {
535 static_cast<TDerived*>(this)->on_receive(msg);
537 }
538
539 //**********************************************
544 //**********************************************
545 template <typename TMessage,
546 typename etl::enable_if< etl::is_message<TMessage>::value && !etl::is_one_of<TMessage, TMessageTypes...>::value, int>::type = 0>
547 void receive(const TMessage& msg)
548 {
549 if (has_successor())
550 {
551 get_successor().receive(msg);
552 }
553 else
554 {
556 static_cast<TDerived*>(this)->on_receive_unknown(msg);
558 }
559 }
560
561 //**********************************************
563 //**********************************************
564 using imessage_router::accepts;
565
566 //**********************************************
569 //***********************************************
570 bool accepts(etl::message_id_t id) const ETL_OVERRIDE
571 {
572 if (id >= Message_Id_Start)
573 {
574 const size_t index = get_dispatch_index_from_message_id(id);
575
576 if (index < Number_Of_Messages)
577 {
578 return true;
579 }
580 }
581
582 return has_successor() ? get_successor().accepts(id) : false;
583 }
584
585 //********************************************
586 ETL_DEPRECATED
587 bool is_null_router() const ETL_OVERRIDE
588 {
589 return false;
590 }
591
592 //********************************************
593 bool is_producer() const ETL_OVERRIDE
594 {
595 return true;
596 }
597
598 //********************************************
599 bool is_consumer() const ETL_OVERRIDE
600 {
601 return true;
602 }
603
604 private:
605
606 static constexpr size_t Number_Of_Messages = sizeof...(TMessageTypes);
607 static constexpr etl::message_id_t Message_Id_Start = etl::type_list_type_at_index_t<sorted_message_types, 0>::ID;
608
609 //**********************************************
610 // Checks that the message ids are contiguous.
611 //**********************************************
612 template <size_t Index, bool Last = (Index + 1U >= Number_Of_Messages)>
613 struct contiguous_impl;
614
615 template <size_t Index>
616 struct contiguous_impl<Index, true> : etl::true_type
617 {
618 };
619
620 template <size_t Index>
621 struct contiguous_impl<Index, false>
622 : etl::bool_constant< (etl::type_list_type_at_index_t<sorted_message_types, Index>::ID + 1U
623 == etl::type_list_type_at_index_t<sorted_message_types, Index + 1U>::ID)
624 && contiguous_impl<Index + 1U>::value>
625 {
626 };
627
628 // The message ids are contiguous if there are 0 or 1 message types, or if
629 // each message id is one greater than the previous message id.
630 static constexpr bool Message_Ids_Are_Contiguous = (Number_Of_Messages <= 1U) ? true : contiguous_impl<0U>::value;
631
632 using handler_ptr = void (*)(TDerived&,
633 const etl::imessage&);
636 using message_dispatch_table_t = etl::array<handler_ptr,
637 Number_Of_Messages>;
640 using message_id_table_t = etl::array<etl::message_id_t,
641 Number_Of_Messages>;
644
645 //**********************************************
646 // Call for a single message type
647 //**********************************************
648 template <typename TMessage>
649 static void call_on_receive(TDerived& derived, const imessage& msg)
650 {
651 derived.on_receive(static_cast<const TMessage&>(msg));
652 }
653
654 //**********************************************
655 // Get the handler for a single message type at the index in the sorted
656 // type_list. This will be called for each message type to generate the
657 // dispatch table.
658 //**********************************************
659 template <size_t Index>
660 static constexpr handler_ptr get_message_handler()
661 {
662 return &call_on_receive< etl::type_list_type_at_index_t<sorted_message_types, Index>>;
663 }
664
665 //**********************************************
666 // Generate the dispatch table at compile time.
667 // This will create an array of handler pointers, one for each message type.
668 //**********************************************
669 template <size_t... Indices>
670 static constexpr message_dispatch_table_t make_message_dispatch_table(etl::index_sequence<Indices...>)
671 {
672 return message_dispatch_table_t{{get_message_handler<Indices>()...}};
673 }
674
675 //**********************************************
676 // Get the message id for a single message type at an index in the sorted
677 // type_list. This will be called for each message type to generate the
678 // message id table.
679 //**********************************************
680 template <size_t Index>
681 static constexpr etl::message_id_t get_message_id_from_index()
682 {
683 return etl::type_list_type_at_index_t<sorted_message_types, Index>::ID;
684 }
685
686 //**********************************************
687 // Generate the message id table at compile time.
688 // This will create an array of message ids, one for each message type.
689 //**********************************************
690 template <size_t... Indices>
691 static constexpr message_id_table_t make_message_id_table(etl::index_sequence<Indices...>)
692 {
693 return message_id_table_t{{get_message_id_from_index<Indices>()...}};
694 }
695
696 //**********************************************
697 // Get the dispatch index for a message id.
698 // This will be used at runtime to find the handler for a message id.
699 // If the message ids are contiguous, we can calculate the index directly.
700 // If they are not contiguous, we need to do a binary search. This will
701 // return Number_Of_Messages if the message id is not found, which indicates
702 // that the message should be passed to the successor.
703 //**********************************************
704 static size_t get_dispatch_index_from_message_id(etl::message_id_t id)
705 {
706 if ETL_IF_CONSTEXPR (Message_Ids_Are_Contiguous)
707 {
708 // The IDs are contiguous, so we can calculate the index directly.
709 return static_cast<size_t>(id - Message_Id_Start);
710 }
711 else
712 {
713 // The IDs are not contiguous, so we need to do a binary search.
714 size_t left = 0;
715 size_t right = Number_Of_Messages;
716
717 while (left < right)
718 {
719 size_t mid = (left + right) / 2;
720
721 if (message_id_table[mid] == id)
722 {
723 return mid;
724 }
725 else if (message_id_table[mid] < id)
726 {
727 left = mid + 1;
728 }
729 else
730 {
731 right = mid;
732 }
733 }
734 }
735
736 return Number_Of_Messages; // Not found
737 }
738
739 //**********************************************
740 // Dispatch the message to the appropriate handler based on the index in the
741 // dispatch table.
742 //**********************************************
743 void dispatch(const etl::imessage& msg, size_t index)
744 {
745 message_dispatch_table[index](static_cast<TDerived&>(*this), msg);
746 }
747
748 //**********************************************
749 // The dispatch table is generated at compile time. The dispatch table
750 // contains pointers to the on_receive handlers for each message type.
751 //**********************************************
752 static ETL_INLINE_VAR constexpr message_dispatch_table_t message_dispatch_table =
753 etl::message_router<TDerived, TMessageTypes...>::make_message_dispatch_table(
754 etl::make_index_sequence< etl::message_router< TDerived, TMessageTypes...>::Number_Of_Messages>{});
755
756 //**********************************************
757 // The message id table is generated at compile time. The message id table
758 // contains the corresponding message ids for each message type.
759 //**********************************************
760 static ETL_INLINE_VAR constexpr message_id_table_t message_id_table = etl::message_router<TDerived, TMessageTypes...>::make_message_id_table(
761 etl::make_index_sequence< etl::message_router< TDerived, TMessageTypes...>::Number_Of_Messages>{});
762 };
763
764 #if ETL_USING_CPP11 && !ETL_USING_CPP17
765 template <typename TDerived, typename... TMessageTypes>
766 constexpr const typename etl::message_router< TDerived, TMessageTypes...>::message_dispatch_table_t
767 etl::message_router<TDerived, TMessageTypes...>::message_dispatch_table;
768
769 template <typename TDerived, typename... TMessageTypes>
770 constexpr const typename etl::message_router< TDerived, TMessageTypes...>::message_id_table_t
771 etl::message_router<TDerived, TMessageTypes...>::message_id_table;
772 #endif
773
774 //***************************************************************************
775 // The definition of a message_router for zero message types.
776 //***************************************************************************
777 template <typename TDerived>
778 class message_router<TDerived>
779 : public imessage_router
781 {
782 public:
783
784 //**********************************************
786 //**********************************************
787 message_router()
788 : imessage_router(etl::imessage_router::MESSAGE_ROUTER)
789 {
790 }
791
792 //**********************************************
795 //**********************************************
796 message_router(etl::imessage_router& successor_)
797 : imessage_router(etl::imessage_router::MESSAGE_ROUTER, successor_)
798 {
799 }
800
801 //**********************************************
802
803 //**********************************************
804 message_router(etl::message_router_id_t id_)
805 : imessage_router(id_)
806 {
807 ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
808 }
809
810 //**********************************************
812 //**********************************************
813 message_router(etl::message_router_id_t id_, etl::imessage_router& successor_)
814 : imessage_router(id_, successor_)
815 {
816 ETL_ASSERT(id_ <= etl::imessage_router::MAX_MESSAGE_ROUTER, ETL_ERROR(etl::message_router_illegal_id));
817 }
818
819 //**********************************************
821 using etl::imessage_router::receive;
822
823 //**********************************************
828 //***********************************************
829 void receive(const etl::imessage& msg) ETL_OVERRIDE
830 {
832 if (has_successor())
833 {
834 get_successor().receive(msg);
835 }
837 }
838
839 //**********************************************
841 //**********************************************
842 using imessage_router::accepts;
843
844 //**********************************************
846 //***********************************************
847 bool accepts(etl::message_id_t id) const ETL_OVERRIDE
848 {
849 if (has_successor())
850 {
851 return get_successor().accepts(id);
852 }
853 else
854 {
855 return false;
856 }
857 }
858
859 //********************************************
860 ETL_DEPRECATED
861 bool is_null_router() const ETL_OVERRIDE
862 {
863 return false;
864 }
865
866 //********************************************
867 bool is_producer() const ETL_OVERRIDE
868 {
869 return true;
870 }
871
872 //********************************************
873 bool is_consumer() const ETL_OVERRIDE
874 {
875 return true;
876 }
877 };
878
879 //***************************************************************************
882 //***************************************************************************
883 template <typename TDerived, typename TList>
884 struct message_router_from_type_list;
885
886 template <typename TDerived, typename... TMessageTypes>
887 struct message_router_from_type_list<TDerived, etl::type_list<TMessageTypes...>>
888 {
889 using type = etl::message_router<TDerived, TMessageTypes...>;
890 };
891
892 template <typename TDerived, typename TTypeList>
893 using message_router_from_type_list_t = typename message_router_from_type_list<TDerived, TTypeList>::type;
894
895#else
896 #include "private/message_router_cpp03.h"
897#endif
898} // namespace etl
899
900#endif
This is the base of all message routers.
Definition message_router.h:141
Definition message.h:73
Definition message_packet.h:42
Base exception class for message router.
Definition message_router.h:54
Router id is out of the legal range.
Definition message_router.h:67
Definition message_router.h:46
Definition message.h:92
Definition message_router.h:125
Definition shared_message.h:50
ETL_NODISCARD etl::imessage & get_message()
Get a reference to the contained message.
Definition shared_message.h:192
Adds successor traits to a class.
Definition successor.h:73
bool has_successor() const
Definition successor.h:184
successor_type & get_successor() const
Definition successor.h:174
Definition message_packet_cpp03.h:41
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
Definition exception.h:59
Definition absolute.h:40
etl::imessage_router & get_null_message_router()
null message router functionality.
Definition message_router.h:295
uint_least8_t message_id_t
Allow alternative type for message id.
Definition message_types.h:40
Definition type_traits.h:97
Is T ultimately derived from etl::imessage_router?
Definition message_router.h:387