Line data Source code
1 : ///////////////////////////////////////////////////////////////////////////
2 : // Inastemp - Berenger Bramas MPCDF - 2016
3 : // Under MIT Licence, please you must read the LICENCE file.
4 : ///////////////////////////////////////////////////////////////////////////
5 : #ifndef INAMEMORY_HPP
6 : #define INAMEMORY_HPP
7 :
8 : #include <cstdint>
9 : #include <cassert>
10 :
11 : /**
12 : * Proposes methods to allocate aligned memory.
13 : * Any memory from this class must be dellocated with
14 : * the Delete method.
15 : * Note: the alignement must be a power of 2
16 : */
17 : class InaMemory {
18 : struct Header{
19 : unsigned char* originPtr;
20 : std::size_t nbElements;
21 : };
22 : const static std::size_t HeaderSize = sizeof(Header);
23 :
24 : template < std::size_t Alignement >
25 : static void* Allocate(const std::size_t inSize, const std::size_t inNbelements) {
26 : // Return null for empty allocation
27 108 : if (inSize == 0) {
28 : return nullptr;
29 : }
30 :
31 : // Ensure it is a power of 2 > 0
32 : static_assert(Alignement != 0 && ((Alignement - 1) & Alignement) == 0, "Alignement must be a power of 2");
33 :
34 : // We will need to store the adress of the real blocks
35 162 : const std::size_t Offset = (Alignement < HeaderSize ? (HeaderSize / Alignement) + 1 : 1) * Alignement;
36 :
37 162 : unsigned char* allocatedMemoryPtr = new unsigned char[inSize + Offset];
38 162 : unsigned char* alignedMemoryPtr = reinterpret_cast< unsigned char* >((reinterpret_cast< std::size_t >(allocatedMemoryPtr) + Offset) & ~(Alignement - 1));
39 : assert((reinterpret_cast< std::size_t >(alignedMemoryPtr) & (Alignement-1)) == 0);
40 :
41 162 : Header* headerPtr = reinterpret_cast<Header*>(alignedMemoryPtr - HeaderSize);
42 :
43 : // Save real address then header value then alignement
44 162 : headerPtr->originPtr = allocatedMemoryPtr;
45 162 : headerPtr->nbElements = inNbelements;
46 :
47 : // Return aligned address
48 : return reinterpret_cast< void* >(alignedMemoryPtr);
49 : }
50 :
51 : public:
52 : template < std::size_t Alignement, class ObjectType >
53 162 : static ObjectType* _new(const std::size_t inNbElementsInArray) {
54 162 : if (inNbElementsInArray == 0) {
55 : return nullptr;
56 : }
57 :
58 162 : const std::size_t sizeInBytes = (inNbElementsInArray * sizeof(ObjectType));
59 :
60 162 : ObjectType* alignedArray = reinterpret_cast< ObjectType* >(Allocate<Alignement>(sizeInBytes, inNbElementsInArray));
61 :
62 972 : for (std::size_t idx = 0; idx < inNbElementsInArray; ++idx) {
63 810 : new (&alignedArray[idx]) ObjectType();
64 : }
65 : return alignedArray;
66 : }
67 :
68 : template < class ObjectType >
69 54 : static void _delete(const ObjectType* ptrToFree) {
70 162 : if (ptrToFree) {
71 162 : const Header* headerPtr = reinterpret_cast<const Header*>(reinterpret_cast< const unsigned char* >(ptrToFree) - HeaderSize);
72 162 : const std::size_t numberOfElements = headerPtr->nbElements;
73 :
74 432 : for (std::size_t idx = 0; idx < numberOfElements; ++idx) {
75 540 : ptrToFree[idx].~ObjectType();
76 : }
77 :
78 162 : delete[] headerPtr->originPtr;
79 : }
80 54 : }
81 : };
82 :
83 :
84 : #endif // INAMEMORY_HPP
|