Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
source/EventQueue/AlignedStorage.h@0:1c7da5f83647, 2016-11-29 (annotated)
- Committer:
- sarahmarshy
- Date:
- Tue Nov 29 06:29:10 2016 +0000
- Revision:
- 0:1c7da5f83647
Initial commit
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| sarahmarshy | 0:1c7da5f83647 | 1 | /* |
| sarahmarshy | 0:1c7da5f83647 | 2 | * Copyright (c) 2016, ARM Limited, All Rights Reserved |
| sarahmarshy | 0:1c7da5f83647 | 3 | * SPDX-License-Identifier: Apache-2.0 |
| sarahmarshy | 0:1c7da5f83647 | 4 | * |
| sarahmarshy | 0:1c7da5f83647 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
| sarahmarshy | 0:1c7da5f83647 | 6 | * not use this file except in compliance with the License. |
| sarahmarshy | 0:1c7da5f83647 | 7 | * You may obtain a copy of the License at |
| sarahmarshy | 0:1c7da5f83647 | 8 | * |
| sarahmarshy | 0:1c7da5f83647 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
| sarahmarshy | 0:1c7da5f83647 | 10 | * |
| sarahmarshy | 0:1c7da5f83647 | 11 | * Unless required by applicable law or agreed to in writing, software |
| sarahmarshy | 0:1c7da5f83647 | 12 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| sarahmarshy | 0:1c7da5f83647 | 13 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| sarahmarshy | 0:1c7da5f83647 | 14 | * See the License for the specific language governing permissions and |
| sarahmarshy | 0:1c7da5f83647 | 15 | * limitations under the License. |
| sarahmarshy | 0:1c7da5f83647 | 16 | */ |
| sarahmarshy | 0:1c7da5f83647 | 17 | #ifndef EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_ |
| sarahmarshy | 0:1c7da5f83647 | 18 | #define EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_ |
| sarahmarshy | 0:1c7da5f83647 | 19 | |
| sarahmarshy | 0:1c7da5f83647 | 20 | #include <cstddef> |
| sarahmarshy | 0:1c7da5f83647 | 21 | |
| sarahmarshy | 0:1c7da5f83647 | 22 | namespace eq { |
| sarahmarshy | 0:1c7da5f83647 | 23 | |
| sarahmarshy | 0:1c7da5f83647 | 24 | class AnonymousDeclaration; |
| sarahmarshy | 0:1c7da5f83647 | 25 | |
| sarahmarshy | 0:1c7da5f83647 | 26 | /** |
| sarahmarshy | 0:1c7da5f83647 | 27 | * Provide aligned raw storage for holding a type T. |
| sarahmarshy | 0:1c7da5f83647 | 28 | * This class is useful to delay the construction of objects while reserving |
| sarahmarshy | 0:1c7da5f83647 | 29 | * space in memory for them. |
| sarahmarshy | 0:1c7da5f83647 | 30 | * For instance, it can be use with static or global variable which can not |
| sarahmarshy | 0:1c7da5f83647 | 31 | * be constructed before main. It can also be used in class member which |
| sarahmarshy | 0:1c7da5f83647 | 32 | * do not have or can't be constructed at parent construction time. |
| sarahmarshy | 0:1c7da5f83647 | 33 | * |
| sarahmarshy | 0:1c7da5f83647 | 34 | * Once the storage has been reserved, it is possible explicitly construct the |
| sarahmarshy | 0:1c7da5f83647 | 35 | * object of T by using placement new syntax. |
| sarahmarshy | 0:1c7da5f83647 | 36 | * @code |
| sarahmarshy | 0:1c7da5f83647 | 37 | * AlignedStorage<Foo> foo; |
| sarahmarshy | 0:1c7da5f83647 | 38 | * new (foo.get_storage()) Foo(...); |
| sarahmarshy | 0:1c7da5f83647 | 39 | * @endcode |
| sarahmarshy | 0:1c7da5f83647 | 40 | * Then it is possible to get a reference to the object by calling the member |
| sarahmarshy | 0:1c7da5f83647 | 41 | * function get. |
| sarahmarshy | 0:1c7da5f83647 | 42 | * @code |
| sarahmarshy | 0:1c7da5f83647 | 43 | * foo.get().doSomething(); |
| sarahmarshy | 0:1c7da5f83647 | 44 | * @endcode |
| sarahmarshy | 0:1c7da5f83647 | 45 | * Once the object needs to be destroyed it is possible to call the destructor |
| sarahmarshy | 0:1c7da5f83647 | 46 | * directly |
| sarahmarshy | 0:1c7da5f83647 | 47 | * @code |
| sarahmarshy | 0:1c7da5f83647 | 48 | * foo.get().~Foo(); |
| sarahmarshy | 0:1c7da5f83647 | 49 | * @endcode |
| sarahmarshy | 0:1c7da5f83647 | 50 | * After this point, their is no instance of T in the storage and the function |
| sarahmarshy | 0:1c7da5f83647 | 51 | * get remains unusable until an object is again initialised in the storage. |
| sarahmarshy | 0:1c7da5f83647 | 52 | */ |
| sarahmarshy | 0:1c7da5f83647 | 53 | template<typename T> |
| sarahmarshy | 0:1c7da5f83647 | 54 | class AlignedStorage { |
| sarahmarshy | 0:1c7da5f83647 | 55 | public: |
| sarahmarshy | 0:1c7da5f83647 | 56 | /** |
| sarahmarshy | 0:1c7da5f83647 | 57 | * Initialisation of the storage, does **not** zeroed its memory. |
| sarahmarshy | 0:1c7da5f83647 | 58 | */ |
| sarahmarshy | 0:1c7da5f83647 | 59 | AlignedStorage() {} |
| sarahmarshy | 0:1c7da5f83647 | 60 | /** |
| sarahmarshy | 0:1c7da5f83647 | 61 | * Provide the raw pointer to the address of the storage. |
| sarahmarshy | 0:1c7da5f83647 | 62 | */ |
| sarahmarshy | 0:1c7da5f83647 | 63 | void* get_storage() { |
| sarahmarshy | 0:1c7da5f83647 | 64 | return data; |
| sarahmarshy | 0:1c7da5f83647 | 65 | } |
| sarahmarshy | 0:1c7da5f83647 | 66 | |
| sarahmarshy | 0:1c7da5f83647 | 67 | /** |
| sarahmarshy | 0:1c7da5f83647 | 68 | * Provide the raw pointer to the const address of the storage. |
| sarahmarshy | 0:1c7da5f83647 | 69 | */ |
| sarahmarshy | 0:1c7da5f83647 | 70 | const void* get_storage() const { |
| sarahmarshy | 0:1c7da5f83647 | 71 | return data; |
| sarahmarshy | 0:1c7da5f83647 | 72 | } |
| sarahmarshy | 0:1c7da5f83647 | 73 | |
| sarahmarshy | 0:1c7da5f83647 | 74 | /** |
| sarahmarshy | 0:1c7da5f83647 | 75 | * Return a reference to the element T in this storage. |
| sarahmarshy | 0:1c7da5f83647 | 76 | */ |
| sarahmarshy | 0:1c7da5f83647 | 77 | T& get() { |
| sarahmarshy | 0:1c7da5f83647 | 78 | return *static_cast<T*>(get_storage()); |
| sarahmarshy | 0:1c7da5f83647 | 79 | } |
| sarahmarshy | 0:1c7da5f83647 | 80 | |
| sarahmarshy | 0:1c7da5f83647 | 81 | /** |
| sarahmarshy | 0:1c7da5f83647 | 82 | * Return a reference to the const element of T in this storage. |
| sarahmarshy | 0:1c7da5f83647 | 83 | */ |
| sarahmarshy | 0:1c7da5f83647 | 84 | const T& get() const { |
| sarahmarshy | 0:1c7da5f83647 | 85 | return *static_cast<const T*>(get_storage()); |
| sarahmarshy | 0:1c7da5f83647 | 86 | } |
| sarahmarshy | 0:1c7da5f83647 | 87 | |
| sarahmarshy | 0:1c7da5f83647 | 88 | private: |
| sarahmarshy | 0:1c7da5f83647 | 89 | // it doesn't make sense to allow copy construction of copy assignement for |
| sarahmarshy | 0:1c7da5f83647 | 90 | // this kind of object. |
| sarahmarshy | 0:1c7da5f83647 | 91 | AlignedStorage(const AlignedStorage&); |
| sarahmarshy | 0:1c7da5f83647 | 92 | AlignedStorage& operator=(const AlignedStorage&); |
| sarahmarshy | 0:1c7da5f83647 | 93 | // storage. Can be improved by metaprogramming to be the best fit. |
| sarahmarshy | 0:1c7da5f83647 | 94 | union { |
| sarahmarshy | 0:1c7da5f83647 | 95 | char char_storage; |
| sarahmarshy | 0:1c7da5f83647 | 96 | short int short_int_storage; |
| sarahmarshy | 0:1c7da5f83647 | 97 | int int_storage; |
| sarahmarshy | 0:1c7da5f83647 | 98 | long int long_int_storage; |
| sarahmarshy | 0:1c7da5f83647 | 99 | float float_storage; |
| sarahmarshy | 0:1c7da5f83647 | 100 | double double_storage; |
| sarahmarshy | 0:1c7da5f83647 | 101 | long double long_double_storage; |
| sarahmarshy | 0:1c7da5f83647 | 102 | void* pointer_storage; |
| sarahmarshy | 0:1c7da5f83647 | 103 | AnonymousDeclaration (*function_pointer_storage)(AnonymousDeclaration); |
| sarahmarshy | 0:1c7da5f83647 | 104 | AnonymousDeclaration* AnonymousDeclaration::*data_member_storage ; |
| sarahmarshy | 0:1c7da5f83647 | 105 | AnonymousDeclaration (AnonymousDeclaration::*function_member_storage)(AnonymousDeclaration); |
| sarahmarshy | 0:1c7da5f83647 | 106 | char data[sizeof(T)]; |
| sarahmarshy | 0:1c7da5f83647 | 107 | }; |
| sarahmarshy | 0:1c7da5f83647 | 108 | }; |
| sarahmarshy | 0:1c7da5f83647 | 109 | |
| sarahmarshy | 0:1c7da5f83647 | 110 | /** |
| sarahmarshy | 0:1c7da5f83647 | 111 | * Provide aligned raw storage for holding an array of type T. |
| sarahmarshy | 0:1c7da5f83647 | 112 | * This is a specialisation of AlignedStorage for arrays of T. |
| sarahmarshy | 0:1c7da5f83647 | 113 | * With this class, it is possible to reserve space for a given number of |
| sarahmarshy | 0:1c7da5f83647 | 114 | * elements of type T and delay their construction to a latter point. This |
| sarahmarshy | 0:1c7da5f83647 | 115 | * feature can be really useful when building generic container which |
| sarahmarshy | 0:1c7da5f83647 | 116 | * embed memory for their elements. Instead of default constructing them, |
| sarahmarshy | 0:1c7da5f83647 | 117 | * the construction of an element can be made when it is really needed, by |
| sarahmarshy | 0:1c7da5f83647 | 118 | * copy. It is the same for the destruction, only objects which have been |
| sarahmarshy | 0:1c7da5f83647 | 119 | * constructed needs to be destructed. |
| sarahmarshy | 0:1c7da5f83647 | 120 | * Those properties improve generic containers because only the operations |
| sarahmarshy | 0:1c7da5f83647 | 121 | * which have to be made are made. It also allow generic container to hold |
| sarahmarshy | 0:1c7da5f83647 | 122 | * types which are not DefaultConstructible. |
| sarahmarshy | 0:1c7da5f83647 | 123 | * |
| sarahmarshy | 0:1c7da5f83647 | 124 | * Once the storage has been reserved, it is possible explicitly construct an |
| sarahmarshy | 0:1c7da5f83647 | 125 | * object of T at a given index by using placement new syntax. |
| sarahmarshy | 0:1c7da5f83647 | 126 | * @code |
| sarahmarshy | 0:1c7da5f83647 | 127 | * AlignedStorage<Foo[10]> foo; |
| sarahmarshy | 0:1c7da5f83647 | 128 | * //construct object at index 0 then at index 1. |
| sarahmarshy | 0:1c7da5f83647 | 129 | * new (foo.get_storage(0)) Foo(...); |
| sarahmarshy | 0:1c7da5f83647 | 130 | * new (foo.get_storage(1)) Foo(...); |
| sarahmarshy | 0:1c7da5f83647 | 131 | * @endcode |
| sarahmarshy | 0:1c7da5f83647 | 132 | * Then it is possible to get a reference to an object at a given index by |
| sarahmarshy | 0:1c7da5f83647 | 133 | * calling the member function get. |
| sarahmarshy | 0:1c7da5f83647 | 134 | * @code |
| sarahmarshy | 0:1c7da5f83647 | 135 | * // do something with object at index 1 |
| sarahmarshy | 0:1c7da5f83647 | 136 | * foo.get(1).doSomething(); |
| sarahmarshy | 0:1c7da5f83647 | 137 | * @endcode |
| sarahmarshy | 0:1c7da5f83647 | 138 | * Once the object needs to be destroyed it is possible to call the destructor |
| sarahmarshy | 0:1c7da5f83647 | 139 | * directly |
| sarahmarshy | 0:1c7da5f83647 | 140 | * @code |
| sarahmarshy | 0:1c7da5f83647 | 141 | * // destroy object at index 1. |
| sarahmarshy | 0:1c7da5f83647 | 142 | * foo.get(1).~Foo(); |
| sarahmarshy | 0:1c7da5f83647 | 143 | * @endcode |
| sarahmarshy | 0:1c7da5f83647 | 144 | * After this point, their is no instance of T at index 1 in the storage and |
| sarahmarshy | 0:1c7da5f83647 | 145 | * trying to use the object at this index will lead to undefined behavior until |
| sarahmarshy | 0:1c7da5f83647 | 146 | * an object is again initialised at this index. |
| sarahmarshy | 0:1c7da5f83647 | 147 | */ |
| sarahmarshy | 0:1c7da5f83647 | 148 | template<typename T, std::size_t ArraySize> |
| sarahmarshy | 0:1c7da5f83647 | 149 | struct AlignedStorage<T[ArraySize]> { |
| sarahmarshy | 0:1c7da5f83647 | 150 | /** |
| sarahmarshy | 0:1c7da5f83647 | 151 | * Initialisation of the storage, does **not** zeroed its memory. |
| sarahmarshy | 0:1c7da5f83647 | 152 | */ |
| sarahmarshy | 0:1c7da5f83647 | 153 | AlignedStorage() {} |
| sarahmarshy | 0:1c7da5f83647 | 154 | |
| sarahmarshy | 0:1c7da5f83647 | 155 | /** |
| sarahmarshy | 0:1c7da5f83647 | 156 | * Return raw pointer to the address of element at a given index |
| sarahmarshy | 0:1c7da5f83647 | 157 | */ |
| sarahmarshy | 0:1c7da5f83647 | 158 | void* get_storage(std::size_t index) { |
| sarahmarshy | 0:1c7da5f83647 | 159 | return &get(index); |
| sarahmarshy | 0:1c7da5f83647 | 160 | } |
| sarahmarshy | 0:1c7da5f83647 | 161 | |
| sarahmarshy | 0:1c7da5f83647 | 162 | /** |
| sarahmarshy | 0:1c7da5f83647 | 163 | * const version of void* get_storage(std::size_t). |
| sarahmarshy | 0:1c7da5f83647 | 164 | */ |
| sarahmarshy | 0:1c7da5f83647 | 165 | const void* get_storage(std::size_t index) const { |
| sarahmarshy | 0:1c7da5f83647 | 166 | return &get(index); |
| sarahmarshy | 0:1c7da5f83647 | 167 | } |
| sarahmarshy | 0:1c7da5f83647 | 168 | |
| sarahmarshy | 0:1c7da5f83647 | 169 | /** |
| sarahmarshy | 0:1c7da5f83647 | 170 | * Return reference to the element stored atindex. |
| sarahmarshy | 0:1c7da5f83647 | 171 | */ |
| sarahmarshy | 0:1c7da5f83647 | 172 | T& get(std::size_t index) { |
| sarahmarshy | 0:1c7da5f83647 | 173 | return reinterpret_cast<T*>(data)[index]; |
| sarahmarshy | 0:1c7da5f83647 | 174 | } |
| sarahmarshy | 0:1c7da5f83647 | 175 | |
| sarahmarshy | 0:1c7da5f83647 | 176 | /** |
| sarahmarshy | 0:1c7da5f83647 | 177 | * const version of T& get(std::size_t). |
| sarahmarshy | 0:1c7da5f83647 | 178 | */ |
| sarahmarshy | 0:1c7da5f83647 | 179 | const T& get(std::size_t index) const { |
| sarahmarshy | 0:1c7da5f83647 | 180 | return reinterpret_cast<const T*>(data)[index]; |
| sarahmarshy | 0:1c7da5f83647 | 181 | } |
| sarahmarshy | 0:1c7da5f83647 | 182 | |
| sarahmarshy | 0:1c7da5f83647 | 183 | private: |
| sarahmarshy | 0:1c7da5f83647 | 184 | // it doesn't make sense to allow copy construction of copy assignement for |
| sarahmarshy | 0:1c7da5f83647 | 185 | // this kind of object. |
| sarahmarshy | 0:1c7da5f83647 | 186 | AlignedStorage(const AlignedStorage&); |
| sarahmarshy | 0:1c7da5f83647 | 187 | AlignedStorage& operator=(const AlignedStorage&); |
| sarahmarshy | 0:1c7da5f83647 | 188 | // storage. Can be improved by metaprogramming to be the best fit. |
| sarahmarshy | 0:1c7da5f83647 | 189 | union { |
| sarahmarshy | 0:1c7da5f83647 | 190 | char char_storage; |
| sarahmarshy | 0:1c7da5f83647 | 191 | short int short_int_storage; |
| sarahmarshy | 0:1c7da5f83647 | 192 | int int_storage; |
| sarahmarshy | 0:1c7da5f83647 | 193 | long int long_int_storage; |
| sarahmarshy | 0:1c7da5f83647 | 194 | float float_storage; |
| sarahmarshy | 0:1c7da5f83647 | 195 | double double_storage; |
| sarahmarshy | 0:1c7da5f83647 | 196 | long double long_double_storage; |
| sarahmarshy | 0:1c7da5f83647 | 197 | void* pointer_storage; |
| sarahmarshy | 0:1c7da5f83647 | 198 | AnonymousDeclaration (*function_pointer_storage)(AnonymousDeclaration); |
| sarahmarshy | 0:1c7da5f83647 | 199 | AnonymousDeclaration* AnonymousDeclaration::*data_member_storage ; |
| sarahmarshy | 0:1c7da5f83647 | 200 | AnonymousDeclaration (AnonymousDeclaration::*function_member_storage)(AnonymousDeclaration); |
| sarahmarshy | 0:1c7da5f83647 | 201 | char data[sizeof(T[ArraySize])]; |
| sarahmarshy | 0:1c7da5f83647 | 202 | }; |
| sarahmarshy | 0:1c7da5f83647 | 203 | }; |
| sarahmarshy | 0:1c7da5f83647 | 204 | |
| sarahmarshy | 0:1c7da5f83647 | 205 | } // namespace eq |
| sarahmarshy | 0:1c7da5f83647 | 206 | |
| sarahmarshy | 0:1c7da5f83647 | 207 | #endif /* EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_ */ |