Sarah Marsh / Mbed OS EddystoneBeacon
Committer:
sarahmarshy
Date:
Tue Nov 29 06:29:10 2016 +0000
Revision:
0:1c7da5f83647
Initial commit

Who changed what in which revision?

UserRevisionLine numberNew 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_ */