Roy Want / Mbed OS beaconCompileReadyFork
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AlignedStorage.h Source File

AlignedStorage.h

00001 /*
00002  * Copyright (c) 2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * not use this file except in compliance with the License.
00007  * You may obtain a copy of the License at
00008  *
00009  * http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
00013  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 #ifndef EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_
00018 #define EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_
00019 
00020 #include <cstddef>
00021 
00022 namespace eq {
00023 
00024 class AnonymousDeclaration;
00025 
00026 /**
00027  * Provide aligned raw storage for holding a type T.
00028  * This class is useful to delay the construction of objects while reserving
00029  * space in memory for them.
00030  * For instance, it can be use with static or global variable which can not
00031  * be constructed before main. It can also be used in class member which
00032  * do not have or can't be constructed at parent construction time.
00033  *
00034  * Once the storage has been reserved, it is possible explicitly construct the
00035  * object of T by using placement new syntax.
00036  * @code
00037  * AlignedStorage<Foo> foo;
00038  * new (foo.get_storage()) Foo(...);
00039  * @endcode
00040  * Then it is possible to get a reference to the object by calling the member
00041  * function get.
00042  * @code
00043  * foo.get().doSomething();
00044  * @endcode
00045  * Once the object needs to be destroyed it is possible to call the destructor
00046  * directly
00047  * @code
00048  * foo.get().~Foo();
00049  * @endcode
00050  * After this point, their is no instance of T in the storage and the function
00051  * get remains unusable until an object is again initialised  in the storage.
00052  */
00053 template<typename T>
00054 class AlignedStorage {
00055 public:
00056     /**
00057      * Initialisation of the storage, does **not** zeroed its memory.
00058      */
00059     AlignedStorage() {}
00060     /**
00061      * Provide the raw pointer to the address of the storage.
00062      */
00063     void* get_storage() {
00064         return data;
00065     }
00066 
00067     /**
00068      * Provide the raw pointer to the const address of the storage.
00069      */
00070     const void* get_storage() const {
00071         return data;
00072     }
00073 
00074     /**
00075      * Return a reference to the element T in this storage.
00076      */
00077     T& get() {
00078         return *static_cast<T*>(get_storage());
00079     }
00080 
00081     /**
00082      * Return a reference to the const element of T in this storage.
00083      */
00084     const T& get() const {
00085         return *static_cast<const T*>(get_storage());
00086     }
00087 
00088 private:
00089     // it doesn't make sense to allow copy construction of copy assignement for
00090     // this kind of object.
00091     AlignedStorage(const AlignedStorage&);
00092     AlignedStorage& operator=(const AlignedStorage&);
00093     // storage. Can be improved by metaprogramming to be the best fit.
00094     union {
00095         char char_storage;
00096         short int short_int_storage;
00097         int int_storage;
00098         long int long_int_storage;
00099         float float_storage;
00100         double double_storage;
00101         long double long_double_storage;
00102         void* pointer_storage;
00103         AnonymousDeclaration (*function_pointer_storage)(AnonymousDeclaration);
00104         AnonymousDeclaration* AnonymousDeclaration::*data_member_storage ;
00105         AnonymousDeclaration (AnonymousDeclaration::*function_member_storage)(AnonymousDeclaration);
00106         char data[sizeof(T)];
00107     };
00108 };
00109 
00110 /**
00111  * Provide aligned raw storage for holding an array of type T.
00112  * This is a specialisation of AlignedStorage for arrays of T.
00113  * With this class, it is possible to reserve space for a given number of
00114  * elements of type T and delay their construction to a latter point. This
00115  * feature can be really useful when building generic container which
00116  * embed memory for their elements. Instead of default constructing them,
00117  * the construction of an element can be made when it is really needed, by
00118  * copy. It is the same for the destruction, only objects which have been
00119  * constructed needs to be destructed.
00120  * Those properties improve generic containers because only the operations
00121  * which have to be made are made. It also allow generic container to hold
00122  * types which are not DefaultConstructible.
00123  *
00124  * Once the storage has been reserved, it is possible explicitly construct an
00125  * object of T at a given index by using placement new syntax.
00126  * @code
00127  * AlignedStorage<Foo[10]> foo;
00128  * //construct object at index 0 then at index 1.
00129  * new (foo.get_storage(0)) Foo(...);
00130  * new (foo.get_storage(1)) Foo(...);
00131  * @endcode
00132  * Then it is possible to get a reference to an object at a given index by
00133  * calling the member function get.
00134  * @code
00135  * // do something with object at index 1
00136  * foo.get(1).doSomething();
00137  * @endcode
00138  * Once the object needs to be destroyed it is possible to call the destructor
00139  * directly
00140  * @code
00141  * // destroy object at index 1.
00142  * foo.get(1).~Foo();
00143  * @endcode
00144  * After this point, their is no instance of T at index 1 in the storage and
00145  * trying to use the object at this index will lead to undefined behavior until
00146  * an object is again initialised at this index.
00147  */
00148 template<typename T, std::size_t ArraySize>
00149 struct AlignedStorage<T[ArraySize]> {
00150     /**
00151      * Initialisation of the storage, does **not** zeroed its memory.
00152      */
00153     AlignedStorage() {}
00154 
00155     /**
00156      * Return raw pointer to the address of element at a given index
00157      */
00158     void* get_storage(std::size_t index) {
00159         return &get(index);
00160     }
00161 
00162     /**
00163      * const version of void* get_storage(std::size_t).
00164      */
00165     const void* get_storage(std::size_t index) const {
00166         return &get(index);
00167     }
00168 
00169     /**
00170      * Return reference to the element stored atindex.
00171      */
00172     T& get(std::size_t index) {
00173         return reinterpret_cast<T*>(data)[index];
00174     }
00175 
00176     /**
00177      * const version of T& get(std::size_t).
00178      */
00179     const T& get(std::size_t index) const {
00180         return reinterpret_cast<const T*>(data)[index];
00181     }
00182 
00183 private:
00184     // it doesn't make sense to allow copy construction of copy assignement for
00185     // this kind of object.
00186     AlignedStorage(const AlignedStorage&);
00187     AlignedStorage& operator=(const AlignedStorage&);
00188     // storage. Can be improved by metaprogramming to be the best fit.
00189     union {
00190         char char_storage;
00191         short int short_int_storage;
00192         int int_storage;
00193         long int long_int_storage;
00194         float float_storage;
00195         double double_storage;
00196         long double long_double_storage;
00197         void* pointer_storage;
00198         AnonymousDeclaration (*function_pointer_storage)(AnonymousDeclaration);
00199         AnonymousDeclaration* AnonymousDeclaration::*data_member_storage ;
00200         AnonymousDeclaration (AnonymousDeclaration::*function_member_storage)(AnonymousDeclaration);
00201         char data[sizeof(T[ArraySize])];
00202     };
00203 };
00204 
00205 } // namespace eq
00206 
00207 #endif /* EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_ */