LCOV - code coverage report
Current view: top level - Src/Common - InaMemory.hpp (source / functions) Hit Total Coverage
Test: Coverage inastemp Lines: 21 21 100.0 %
Date: 2022-03-17 09:48:28 Functions: 19 19 100.0 %

          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

Generated by: LCOV version 1.13