Embedded Template Library 1.0
Loading...
Searching...
No Matches
message_packet.h
1/******************************************************************************
2The MIT License(MIT)
3
4Embedded Template Library.
5https://github.com/ETLCPP/etl
6https://www.etlcpp.com
7
8Copyright(c) 2020 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_PACKET_INCLUDED
30#define ETL_MESSAGE_PACKET_INCLUDED
31
32#include "platform.h"
33
34#include "alignment.h"
35#include "error_handler.h"
36#include "largest.h"
37#include "message.h"
38#include "static_assert.h"
39#include "type_list.h"
40#include "utility.h"
42namespace etl
43{
44#if ETL_USING_CPP17 && !defined(ETL_MESSAGE_PACKET_FORCE_CPP03_IMPLEMENTATION)
45 //***************************************************************************
46 // The definition for all message types.
47 //***************************************************************************
48 template <typename... TMessageTypes>
49 class message_packet
50 {
51 private:
52
53 template <typename T>
54 static constexpr bool IsMessagePacket = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<TMessageTypes...>>;
55
56 template <typename T>
57 static constexpr bool IsInMessageList = etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<T>>, TMessageTypes...>;
58
59 template <typename T>
60 static constexpr bool IsIMessage = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
61
62 public:
63
64 using message_types = etl::type_list<TMessageTypes...>;
65
66 //********************************************
68 constexpr message_packet() noexcept
69 : valid(false)
70 {
71 }
73
74 //********************************************
76 //********************************************
78 template <typename T, typename = typename etl::enable_if< IsIMessage<T> || IsInMessageList<T>, int>::type>
79 explicit message_packet(T&& msg)
80 : valid(true)
81 {
82 if constexpr (IsIMessage<T>)
83 {
84 if (accepts(msg))
85 {
86 add_new_message(etl::forward<T>(msg));
87 valid = true;
88 }
89 else
90 {
91 valid = false;
92 }
93
94 ETL_ASSERT(valid, ETL_ERROR(unhandled_message_exception));
95 }
96 else if constexpr (IsInMessageList<T>)
97 {
98 add_new_message_type<T>(etl::forward<T>(msg));
99 }
100 else
101 {
102 ETL_STATIC_ASSERT(IsInMessageList<T>, "Message not in packet type list");
103 }
104 }
105 #include "private/diagnostic_pop.h"
106
107 //**********************************************
108 message_packet(const message_packet& other)
109 {
110 valid = other.is_valid();
111
112 if (valid)
113 {
114 add_new_message(other.get());
115 }
116 }
117
118 #if ETL_USING_CPP11
119 //**********************************************
120 message_packet(message_packet&& other)
121 {
122 valid = other.is_valid();
123
124 if (valid)
125 {
126 add_new_message(etl::move(other.get()));
127 }
128 }
129 #endif
130
131 //**********************************************
132 void copy(const message_packet& other)
133 {
134 valid = other.is_valid();
135
136 if (valid)
137 {
138 add_new_message(other.get());
139 }
140 }
141
142 //**********************************************
143 void copy(message_packet&& other)
144 {
145 valid = other.is_valid();
146
147 if (valid)
148 {
149 add_new_message(etl::move(other.get()));
150 }
151 }
152
153 //**********************************************
155 message_packet& operator=(const message_packet& rhs)
156 {
157 delete_current_message();
158 valid = rhs.is_valid();
159 if (valid)
160 {
161 add_new_message(rhs.get());
162 }
163
164 return *this;
165 }
166 #include "private/diagnostic_pop.h"
167
168 //**********************************************
170 message_packet& operator=(message_packet&& rhs)
171 {
172 delete_current_message();
173 valid = rhs.is_valid();
174 if (valid)
175 {
176 add_new_message(etl::move(rhs.get()));
177 }
178
179 return *this;
180 }
181 #include "private/diagnostic_pop.h"
182
183 //********************************************
184 ~message_packet()
185 {
186 delete_current_message();
187 }
188
189 //********************************************
190 etl::imessage& get() ETL_NOEXCEPT
191 {
192 return *static_cast<etl::imessage*>(data);
193 }
194
195 //********************************************
196 const etl::imessage& get() const ETL_NOEXCEPT
197 {
198 return *static_cast<const etl::imessage*>(data);
199 }
200
201 //********************************************
202 bool is_valid() const
203 {
204 return valid;
205 }
206
207 //**********************************************
208 static ETL_CONSTEXPR bool accepts(etl::message_id_t id)
209 {
210 return (accepts_message<TMessageTypes::ID>(id) || ...);
211 }
212
213 //**********************************************
214 static ETL_CONSTEXPR bool accepts(const etl::imessage& msg)
215 {
216 return accepts(msg.get_message_id());
217 }
218
219 //**********************************************
220 template <etl::message_id_t Id>
221 static ETL_CONSTEXPR bool accepts()
222 {
223 return (accepts_message<TMessageTypes::ID, Id>() || ...);
224 }
225
226 //**********************************************
227 template <typename TMessage>
228 static ETL_CONSTEXPR typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type accepts()
229 {
230 return accepts<TMessage::ID>();
231 }
232
233 enum
234 {
235 SIZE = etl::largest<TMessageTypes...>::size,
236 ALIGNMENT = etl::largest<TMessageTypes...>::alignment
237 };
238
239 private:
240
241 //**********************************************
242 template <etl::message_id_t Id1, etl::message_id_t Id2>
243 static bool accepts_message()
244 {
245 return Id1 == Id2;
246 }
247
248 //**********************************************
249 template <etl::message_id_t Id1>
250 static bool accepts_message(etl::message_id_t id2)
251 {
252 return Id1 == id2;
253 }
254
255 //********************************************
257 void delete_current_message()
258 {
259 if (valid)
260 {
261 etl::imessage* pmsg = static_cast<etl::imessage*>(data);
262
263 #if ETL_HAS_VIRTUAL_MESSAGES
264 pmsg->~imessage();
265 #else
266 delete_message(pmsg);
267 #endif
268 }
269 }
270 #include "private/diagnostic_pop.h"
271
272 #if !ETL_HAS_VIRTUAL_MESSAGES
273 //********************************************
274 void delete_message(etl::imessage* pmsg)
275 {
276 (delete_message_type<TMessageTypes>(pmsg) || ...);
277 }
278
279 //********************************************
280 template <typename TType>
281 bool delete_message_type(etl::imessage* pmsg)
282 {
283 if (TType::ID == pmsg->get_message_id())
284 {
285 TType* p = static_cast<TType*>(pmsg);
286 p->~TType();
287 return true;
288 }
289 else
290 {
291 return false;
292 }
293 }
294 #endif
295
296 //********************************************
297 void add_new_message(const etl::imessage& msg)
298 {
299 (add_new_message_type<TMessageTypes>(msg) || ...);
300 }
301
302 //********************************************
303 void add_new_message(etl::imessage&& msg)
304 {
305 (add_new_message_type<TMessageTypes>(etl::move(msg)) || ...);
306 }
307
309 //********************************************
311 //********************************************
312 template <typename TMessage>
313 etl::enable_if_t< etl::is_one_of_v<etl::remove_const_t<etl::remove_reference_t<TMessage>>, TMessageTypes...>, void>
314 add_new_message_type(TMessage&& msg)
315 {
316 void* p = data;
317 new (p) etl::remove_reference_t<TMessage>((etl::forward<TMessage>(msg)));
318 }
319 #include "private/diagnostic_pop.h"
320
322 //********************************************
323 template <typename TType>
324 bool add_new_message_type(const etl::imessage& msg)
325 {
326 if (TType::ID == msg.get_message_id())
327 {
328 void* p = data;
329 new (p) TType(static_cast<const TType&>(msg));
330 return true;
331 }
332 else
333 {
334 return false;
335 }
336 }
337 #include "private/diagnostic_pop.h"
338
340 //********************************************
341 template <typename TType>
342 bool add_new_message_type(etl::imessage&& msg)
343 {
344 if (TType::ID == msg.get_message_id())
345 {
346 void* p = data;
347 new (p) TType(static_cast<TType&&>(msg));
348 return true;
349 }
350 else
351 {
352 return false;
353 }
354 }
355 #include "private/diagnostic_pop.h"
356
358 bool valid;
359 };
360
361 //***************************************************************************
362 // The definition for no message types.
363 //***************************************************************************
364 template <>
365 class message_packet<>
366 {
367 private:
369 template <typename T>
370 static constexpr bool IsMessagePacket = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::message_packet<>>;
371
372 template <typename T>
373 static constexpr bool IsInMessageList = false;
374
375 template <typename T>
376 static constexpr bool IsIMessage = etl::is_same_v<etl::remove_const_t<etl::remove_reference_t<T>>, etl::imessage>;
377
378 public:
379
380 using message_types = etl::type_list<>;
381
382 //********************************************
384 constexpr message_packet() noexcept {}
385 #include "private/diagnostic_pop.h"
386
387 //**********************************************
388 message_packet(const message_packet& /*other*/) {}
389
390 #if ETL_USING_CPP11
391 //**********************************************
392 message_packet(message_packet&& /*other*/) {}
393 #endif
394
395 //**********************************************
396 void copy(const message_packet& /*other*/) {}
397
398 //**********************************************
399 void copy(message_packet&& /*other*/) {}
400
401 //**********************************************
403 message_packet& operator=(const message_packet& /*rhs*/)
404 {
405 return *this;
406 }
407 #include "private/diagnostic_pop.h"
408
409 //**********************************************
411 message_packet& operator=(message_packet&& /*rhs*/)
412 {
413 return *this;
414 }
415 #include "private/diagnostic_pop.h"
416
417 //********************************************
418 ~message_packet() {}
419
420 //********************************************
421 bool is_valid() const
422 {
423 return false;
424 }
425
426 //**********************************************
427 static ETL_CONSTEXPR bool accepts(etl::message_id_t /*id*/)
428 {
429 return false;
430 }
431
432 //**********************************************
433 static ETL_CONSTEXPR bool accepts(const etl::imessage& /*msg*/)
434 {
435 return false;
436 }
437
438 //**********************************************
439 template <etl::message_id_t Id>
440 static ETL_CONSTEXPR bool accepts()
441 {
442 return false;
443 }
444
445 //**********************************************
446 template <typename TMessage>
447 static ETL_CONSTEXPR typename etl::enable_if<etl::is_base_of<etl::imessage, TMessage>::value, bool>::type accepts()
448 {
449 return false;
450 }
451
452 enum
453 {
454 SIZE = 0,
455 ALIGNMENT = 1
456 };
457 };
458
459 //***************************************************************************
462 template <typename TList>
463 struct message_packet_from_type_list;
464
465 template <typename... TTypes>
466 struct message_packet_from_type_list<etl::type_list<TTypes...>>
467 {
468 using type = etl::message_packet<TTypes...>;
469 };
470
471 template <typename TTypeList>
472 using message_packet_from_type_list_t = typename message_packet_from_type_list<TTypeList>::type;
473
474#else
475 #include "private/message_packet_cpp03.h"
476#endif
477} // namespace etl
478
479#endif
Definition message.h:73
Definition message_packet.h:42
Definition message.h:54
Definition message_packet_cpp03.h:41
Make this a clone of the supplied priority queue.
#define ETL_ASSERT(b, e)
Definition error_handler.h:511
Definition largest.h:45
Definition absolute.h:40
uint_least8_t message_id_t
Allow alternative type for message id.
Definition message_types.h:40
ETL_CONSTEXPR TContainer::size_type size(const TContainer &container)
Definition iterator.h:1434
Definition alignment.h:253