Embedded Template Library 1.0
Loading...
Searching...
No Matches
alignment.h
Go to the documentation of this file.
1
2
3/******************************************************************************
4The MIT License(MIT)
5
6Embedded Template Library.
7https://github.com/ETLCPP/etl
8https://www.etlcpp.com
9
10Copyright(c) 2014 John Wellbelove
11
12Permission is hereby granted, free of charge, to any person obtaining a copy
13of this software and associated documentation files(the "Software"), to deal
14in the Software without restriction, including without limitation the rights
15to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
16copies of the Software, and to permit persons to whom the Software is
17furnished to do so, subject to the following conditions :
18
19The above copyright notice and this permission notice shall be included in all
20copies or substantial portions of the Software.
21
22THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
25AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28SOFTWARE.
29******************************************************************************/
30
31#ifndef ETL_ALIGNMENT_INCLUDED
32#define ETL_ALIGNMENT_INCLUDED
33
34#include "platform.h"
35#include "type_traits.h"
36#include "static_assert.h"
37#include "error_handler.h"
38#include "exception.h"
39#include "utility.h"
40
41#include <stdint.h>
42
46
47namespace etl
48{
49 //***************************************************************************
51 //***************************************************************************
53 {
54 public:
55
56 alignment_exception(string_type reason_, string_type file_name_, numeric_type line_number_)
58 {
59 }
60 };
61
62 //***************************************************************************
64 //***************************************************************************
66 {
67 public:
68
69 alignment_error(string_type file_name_, numeric_type line_number_)
70 : alignment_exception(ETL_ERROR_TEXT("alignment:error", ETL_ALIGNMENT_FILE_ID"A"), file_name_, line_number_)
71 {
72 }
73 };
74
75 //***************************************************************************
77 //***************************************************************************
79 {
80 public:
81
82 typed_storage_error(string_type file_name_, numeric_type line_number_)
83 : alignment_exception(ETL_ERROR_TEXT("typed_storage:error", ETL_ALIGNMENT_FILE_ID"B"), file_name_, line_number_)
84 {
85 }
86 };
87
88 //*****************************************************************************
90 //*****************************************************************************
91 inline bool is_aligned(const void* p, size_t required_alignment)
92 {
93 uintptr_t address = reinterpret_cast<uintptr_t>(p);
94 return (address % required_alignment) == 0U;
95 }
96
97 //*****************************************************************************
99 //*****************************************************************************
100 template <size_t Alignment>
101 bool is_aligned(const void* p)
102 {
103 uintptr_t address = reinterpret_cast<uintptr_t>(p);
104 return (address % Alignment) == 0U;
105 }
106
107 //*****************************************************************************
109 //*****************************************************************************
110 template <typename T>
111 bool is_aligned(const void* p)
112 {
114 }
115
116 namespace private_alignment
117 {
118#if ETL_USING_CPP11
119 //***************************************************************************
120 // Matcher.
121 //***************************************************************************
122 template <bool Is_Match, size_t Alignment, typename... TRest>
123 class type_with_alignment_matcher;
124
125 // Matching alignment.
126 template <size_t Alignment, typename T1, typename... TRest>
127 class type_with_alignment_matcher<true, Alignment, T1, TRest...>
128 {
129 public:
130
131 typedef T1 type;
132 };
133
134 // Non-matching alignment
135 template <size_t Alignment, typename T1, typename T2, typename... TRest>
136 class type_with_alignment_matcher <false, Alignment, T1, T2, TRest...>
137 {
138 public:
139
140 typedef typename type_with_alignment_matcher < Alignment <= etl::alignment_of<T2>::value , Alignment, T2, TRest... > ::type type;
141 };
142
143 // Non-matching alignment, none left.
144 template <size_t Alignment, typename T1>
145 class type_with_alignment_matcher <false, Alignment, T1>
146 {
147 public:
148
149 typedef char type;
150 };
151
152 //***************************************************************************
153 // Helper.
154 //***************************************************************************
155 template <size_t Alignment, typename T1, typename... T>
156 class type_with_alignment_helper
157 {
158 public:
159
160 typedef typename type_with_alignment_matcher<Alignment <= etl::alignment_of<T1>::value, Alignment, T1, T...>::type type;
161 };
162#else
163 //***************************************************************************
164 // Matcher.
165 //***************************************************************************
166 template <bool Is_Match, const size_t Alignment, typename T1 = void, typename T2 = void, typename T3 = void, typename T4 = void,
167 typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
169
170 // Matching alignment.
171 template <size_t Alignment, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
172 class type_with_alignment_matcher <true, Alignment, T1, T2, T3, T4, T5, T6, T7, T8>
173 {
174 public:
175
176 typedef T1 type;
177 };
178
179 // Non-matching alignment.
180 template <size_t Alignment, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
181 class type_with_alignment_matcher <false, Alignment, T1, T2, T3, T4, T5, T6, T7, T8>
182 {
183 public:
184
185 typedef typename type_with_alignment_matcher<Alignment <= etl::alignment_of<T2>::value, Alignment, T2, T3, T4, T5, T6, T7, T8, void>::type type;
186 };
187
188 // Non-matching alignment, none left.
189 template <size_t Alignment>
190 class type_with_alignment_matcher <false, Alignment, void, void, void, void, void, void, void, void>
191 {
192 public:
193
194 typedef char type;
195 };
196
197 //***************************************************************************
198 // Helper.
199 //***************************************************************************
200 template <size_t Alignment, typename T1, typename T2 = void, typename T3 = void, typename T4 = void,
201 typename T5 = void, typename T6 = void, typename T7 = void, typename T8 = void>
203 {
204 public:
205
206 typedef typename type_with_alignment_matcher<Alignment <= etl::alignment_of<T1>::value, Alignment, T1, T2, T3, T4, T5, T6, T7, T8>::type type;
207 };
208#endif
209 }
210
211 //***************************************************************************
214 //***************************************************************************
215 template <size_t Alignment>
217 {
218 public:
219
220#if ETL_USING_CPP11
221 typedef struct { alignas(Alignment) char dummy; } type;
222#else
223 #if ETL_NOT_USING_64BIT_TYPES
225 #else
227 #endif
228#endif
229
230 ETL_STATIC_ASSERT(etl::alignment_of<type>::value == Alignment, "Unable to create the type with the specified alignment");
231 };
232
233#if ETL_USING_CPP11
234 template <size_t Alignment>
235 using type_with_alignment_t = typename type_with_alignment<Alignment>::type;
236#endif
237
238 //***************************************************************************
242 //***************************************************************************
243 template <size_t Length, const size_t Alignment>
245 {
246 struct type
247 {
248 //type()
249 // : data()
250 //{
251 //}
252
254 template <typename T>
255 operator T& ()
256 {
257 ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
258 T* t = *this;
259 return *t;
260 }
261
263 template <typename T>
264 operator const T& () const
265 {
266 ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
267 const T* t = *this;
268 return *t;
269 }
270
272 template <typename T>
273 operator T* ()
274 {
275 ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
276 return reinterpret_cast<T*>(data);
277 }
278
280 template <typename T>
281 operator const T* () const
282 {
283 ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
284 return reinterpret_cast<const T*>(data);
285 }
286
288 template <typename T>
290 {
291 ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
292 T* t = *this;
293 return *t;
294 }
295
297 template <typename T>
298 const T& get_reference() const
299 {
300 ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
301 const T* t = *this;
302 return *t;
303 }
304
306 template <typename T>
308 {
309 ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
310 return reinterpret_cast<T*>(data);
311 }
312
314 template <typename T>
315 const T* get_address() const
316 {
317 ETL_STATIC_ASSERT((etl::is_same<T*, void*>:: value || ((Alignment % etl::alignment_of<T>::value) == 0)), "Incompatible alignment");
318 return reinterpret_cast<const T*>(data);
319 }
320
321#if ETL_USING_CPP11 && !defined(ETL_COMPILER_ARM5)
322 alignas(Alignment) char data[Length];
323#else
324 union
325 {
326 char data[Length];
327 typename etl::type_with_alignment<Alignment>::type etl_alignment_type; // A POD type that has the same alignment as Alignment.
328 };
329#endif
330 };
331 };
332
333#if ETL_USING_CPP11
334 template <size_t Length, const size_t Alignment>
335 using aligned_storage_t = typename aligned_storage<Length, Alignment>::type;
336#endif
337
338 //***************************************************************************
341 //***************************************************************************
342 template <size_t Length, typename T>
343 struct aligned_storage_as : public etl::aligned_storage<Length, etl::alignment_of<T>::value>
344 {
345 };
346
347#if ETL_USING_CPP11
348 template <size_t Length, typename T>
350#endif
351
352 //***************************************************************************
359 //***************************************************************************
360 template <typename T>
362 {
363 public:
364
365 typedef T value_type;
366 typedef T& reference;
367 typedef const T& const_reference;
368 typedef T* pointer;
369 typedef const T* const_pointer;
370
371 // Constructor
373 : valid(false)
374 {
375 }
376
377 //***************************************************************************
380 //***************************************************************************
382 {
383 }
384
385 //***************************************************************************
388 //***************************************************************************
389 bool has_value() const
390 {
391 return valid;
392 }
393
394#if ETL_USING_CPP11
395 //***************************************************************************
400 //***************************************************************************
401 template<typename... Args>
402 reference create(Args&&... args)
403 {
405 valid = true;
406 return *::new (data.template get_address<char>()) value_type(etl::forward<Args>(args)...);
407 }
408#else
409 //***************************************************************************
414 //***************************************************************************
415 template<typename T1>
416 reference create(const T1& t1)
417 {
419 valid = true;
420 return *::new (data.template get_address<char>()) value_type(t1);
421 }
422
423 //***************************************************************************
428 //***************************************************************************
429 template<typename T1, typename T2>
430 reference create(const T1& t1, const T2& t2)
431 {
433 valid = true;
434 return *::new (data.template get_address<char>()) value_type(t1, t2);
435 }
436
437 //***************************************************************************
442 //***************************************************************************
443 template<typename T1, typename T2, typename T3>
444 reference create(const T1& t1, const T2& t2, const T3& t3)
445 {
447 valid = true;
448 return *::new (data.template get_address<char>()) value_type(t1, t2, t3);
449 }
450
451 //***************************************************************************
456 //***************************************************************************
457 template<typename T1, typename T2, typename T3, typename T4>
458 reference create(const T1& t1, const T2& t2, const T3& t3, const T4& t4)
459 {
461 valid = true;
462 return *::new (data.template get_address<char>()) value_type(t1, t2, t3, t4);
463 }
464#endif
465
466 //***************************************************************************
468 //***************************************************************************
469 void destroy()
470 {
472 data.template get_reference<T>().~T();
473 valid = false;
474 }
475
476 //***************************************************************************
478 //***************************************************************************
479 pointer operator->()
480 {
482 return data.template get_address<value_type>();
483 }
484
485 //***************************************************************************
487 //***************************************************************************
488 const_pointer operator->() const
489 {
490 return operator->();
491 }
492
493 //***************************************************************************
495 //***************************************************************************
496 reference operator*()
497 {
498 return *operator->();
499 }
500
501 //***************************************************************************
503 //***************************************************************************
504 const_reference operator*() const
505 {
506 return *operator->();
507 }
508
509 private:
510
511 typename aligned_storage_as<sizeof(value_type), value_type>::type data;
512 bool valid;
513 };
514}
515
516#endif
Memory misalignment exception.
Definition alignment.h:66
Exception base for alignment.
Definition alignment.h:53
Typed storage exception.
Definition alignment.h:79
Definition alignment.h:362
reference create(const T1 &t1, const T2 &t2)
Definition alignment.h:430
reference operator*()
Definition alignment.h:496
const_pointer operator->() const
Definition alignment.h:488
pointer operator->()
Definition alignment.h:479
reference create(const T1 &t1)
Definition alignment.h:416
const_reference operator*() const
Definition alignment.h:504
~typed_storage()
Definition alignment.h:381
reference create(const T1 &t1, const T2 &t2, const T3 &t3)
Definition alignment.h:444
void destroy()
Calls the destructor of the wrapped object and asserts if has_value() is false.
Definition alignment.h:469
reference create(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4)
Definition alignment.h:458
bool has_value() const
Definition alignment.h:389
Definition alignment.h:217
Definition alignment.h:245
Definition alignment.h:344
#define ETL_ASSERT(b, e)
Definition error_handler.h:356
Definition exception.h:47
add_rvalue_reference
Definition type_traits_generator.h:1366
is_same
Definition type_traits_generator.h:1080
bitset_ext
Definition absolute.h:38
bool is_aligned(const void *p, size_t required_alignment)
Check that 'p' has 'required_alignment'.
Definition alignment.h:91
ETL_NODISCARD ETL_CONSTEXPR14 T round_half_even_unscaled(T value) ETL_NOEXCEPT
Definition scaled_rounding.h:314
Definition alignment.h:247
const T * get_address() const
Get address as const T pointer.
Definition alignment.h:315
T * get_address()
Get address as T pointer.
Definition alignment.h:307
const T & get_reference() const
Get address as const T reference.
Definition alignment.h:298
T & get_reference()
Get address as T reference.
Definition alignment.h:289