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
- Committer:
- roywant
- Date:
- 2016-09-19
- Revision:
- 0:ed0152b5c495
File content as of revision 0:ed0152b5c495:
/*
* Copyright (c) 2016, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_
#define EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_
#include <cstddef>
namespace eq {
class AnonymousDeclaration;
/**
* Provide aligned raw storage for holding a type T.
* This class is useful to delay the construction of objects while reserving
* space in memory for them.
* For instance, it can be use with static or global variable which can not
* be constructed before main. It can also be used in class member which
* do not have or can't be constructed at parent construction time.
*
* Once the storage has been reserved, it is possible explicitly construct the
* object of T by using placement new syntax.
* @code
* AlignedStorage<Foo> foo;
* new (foo.get_storage()) Foo(...);
* @endcode
* Then it is possible to get a reference to the object by calling the member
* function get.
* @code
* foo.get().doSomething();
* @endcode
* Once the object needs to be destroyed it is possible to call the destructor
* directly
* @code
* foo.get().~Foo();
* @endcode
* After this point, their is no instance of T in the storage and the function
* get remains unusable until an object is again initialised in the storage.
*/
template<typename T>
class AlignedStorage {
public:
/**
* Initialisation of the storage, does **not** zeroed its memory.
*/
AlignedStorage() {}
/**
* Provide the raw pointer to the address of the storage.
*/
void* get_storage() {
return data;
}
/**
* Provide the raw pointer to the const address of the storage.
*/
const void* get_storage() const {
return data;
}
/**
* Return a reference to the element T in this storage.
*/
T& get() {
return *static_cast<T*>(get_storage());
}
/**
* Return a reference to the const element of T in this storage.
*/
const T& get() const {
return *static_cast<const T*>(get_storage());
}
private:
// it doesn't make sense to allow copy construction of copy assignement for
// this kind of object.
AlignedStorage(const AlignedStorage&);
AlignedStorage& operator=(const AlignedStorage&);
// storage. Can be improved by metaprogramming to be the best fit.
union {
char char_storage;
short int short_int_storage;
int int_storage;
long int long_int_storage;
float float_storage;
double double_storage;
long double long_double_storage;
void* pointer_storage;
AnonymousDeclaration (*function_pointer_storage)(AnonymousDeclaration);
AnonymousDeclaration* AnonymousDeclaration::*data_member_storage ;
AnonymousDeclaration (AnonymousDeclaration::*function_member_storage)(AnonymousDeclaration);
char data[sizeof(T)];
};
};
/**
* Provide aligned raw storage for holding an array of type T.
* This is a specialisation of AlignedStorage for arrays of T.
* With this class, it is possible to reserve space for a given number of
* elements of type T and delay their construction to a latter point. This
* feature can be really useful when building generic container which
* embed memory for their elements. Instead of default constructing them,
* the construction of an element can be made when it is really needed, by
* copy. It is the same for the destruction, only objects which have been
* constructed needs to be destructed.
* Those properties improve generic containers because only the operations
* which have to be made are made. It also allow generic container to hold
* types which are not DefaultConstructible.
*
* Once the storage has been reserved, it is possible explicitly construct an
* object of T at a given index by using placement new syntax.
* @code
* AlignedStorage<Foo[10]> foo;
* //construct object at index 0 then at index 1.
* new (foo.get_storage(0)) Foo(...);
* new (foo.get_storage(1)) Foo(...);
* @endcode
* Then it is possible to get a reference to an object at a given index by
* calling the member function get.
* @code
* // do something with object at index 1
* foo.get(1).doSomething();
* @endcode
* Once the object needs to be destroyed it is possible to call the destructor
* directly
* @code
* // destroy object at index 1.
* foo.get(1).~Foo();
* @endcode
* After this point, their is no instance of T at index 1 in the storage and
* trying to use the object at this index will lead to undefined behavior until
* an object is again initialised at this index.
*/
template<typename T, std::size_t ArraySize>
struct AlignedStorage<T[ArraySize]> {
/**
* Initialisation of the storage, does **not** zeroed its memory.
*/
AlignedStorage() {}
/**
* Return raw pointer to the address of element at a given index
*/
void* get_storage(std::size_t index) {
return &get(index);
}
/**
* const version of void* get_storage(std::size_t).
*/
const void* get_storage(std::size_t index) const {
return &get(index);
}
/**
* Return reference to the element stored atindex.
*/
T& get(std::size_t index) {
return reinterpret_cast<T*>(data)[index];
}
/**
* const version of T& get(std::size_t).
*/
const T& get(std::size_t index) const {
return reinterpret_cast<const T*>(data)[index];
}
private:
// it doesn't make sense to allow copy construction of copy assignement for
// this kind of object.
AlignedStorage(const AlignedStorage&);
AlignedStorage& operator=(const AlignedStorage&);
// storage. Can be improved by metaprogramming to be the best fit.
union {
char char_storage;
short int short_int_storage;
int int_storage;
long int long_int_storage;
float float_storage;
double double_storage;
long double long_double_storage;
void* pointer_storage;
AnonymousDeclaration (*function_pointer_storage)(AnonymousDeclaration);
AnonymousDeclaration* AnonymousDeclaration::*data_member_storage ;
AnonymousDeclaration (AnonymousDeclaration::*function_member_storage)(AnonymousDeclaration);
char data[sizeof(T[ArraySize])];
};
};
} // namespace eq
#endif /* EVENTQUEUE_DETAIL_ALIGNEDSTORAGE_H_ */