Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-12 09:18:01

0001 // Created on: 2013-11-12
0002 // Created by: Maxim YAKUNIN (myn)
0003 // Copyright (c) 2002-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef NCollection_AccAllocator_HeaderFile
0017 #define NCollection_AccAllocator_HeaderFile
0018 
0019 #include <NCollection_BaseAllocator.hxx>
0020 #include <NCollection_DataMap.hxx>
0021 
0022 //!
0023 //! Class NCollection_AccAllocator - accumulating memory allocator. This
0024 //! class allocates memory on request returning the pointer to the allocated
0025 //! space. The allocation units are grouped in blocks requested from the
0026 //! system as required. This memory is returned to the system when all
0027 //! allocations in a block are freed.
0028 //!
0029 //! By comparison with the standard new() and malloc() calls, this method is
0030 //! faster and consumes very small additional memory to maintain the heap.
0031 //!
0032 //! By comparison with NCollection_IncAllocator, this class requires some more
0033 //! additional memory and a little more time for allocation and deallocation.
0034 //! Memory overhead for NCollection_IncAllocator is 12 bytes per block;
0035 //! average memory overhead for NCollection_AccAllocator is 28 bytes per block.
0036 //!
0037 //! All pointers returned by Allocate() are aligned to 4 byte boundaries.
0038 //! To define the sizeof memory blocks requested from the OS, use the
0039 //! parameter of the constructor (measured in bytes).
0040 
0041 class NCollection_AccAllocator : public NCollection_BaseAllocator
0042 {
0043   // --------- PUBLIC CONSTANTS ---------
0044 public:
0045   //! Alignment of all allocated objects: 4 bytes
0046   static constexpr size_t Align = 4;
0047 
0048   //! Default block size
0049   static constexpr size_t DefaultBlockSize = 24600;
0050 
0051   //! Number of last blocks to check for free space
0052   static constexpr int MaxLookupBlocks = 16;
0053 
0054   // ---------- PUBLIC METHODS ----------
0055 public:
0056   //! Constructor
0057   Standard_EXPORT NCollection_AccAllocator(const size_t theBlockSize = DefaultBlockSize);
0058 
0059   //! Destructor
0060   Standard_EXPORT ~NCollection_AccAllocator() override;
0061 
0062   //! Allocate memory with given size
0063   Standard_EXPORT void* Allocate(const size_t theSize) override;
0064 
0065   //! Allocate memory with given size
0066   void* AllocateOptimal(const size_t theSize) override { return Allocate(theSize); }
0067 
0068   //! Free a previously allocated memory;
0069   //! memory is returned to the OS when all allocations in some block are freed
0070   Standard_EXPORT void Free(void* theAddress) override;
0071 
0072   // --------- PROTECTED TYPES ---------
0073 protected:
0074   //! Size value aligned to a 4 byte boundary
0075   class AlignedSize
0076   {
0077     size_t myValue;
0078 
0079   public:
0080     constexpr AlignedSize() noexcept
0081         : myValue(0)
0082     {
0083     }
0084 
0085     constexpr AlignedSize(const size_t theValue) noexcept
0086         : myValue((theValue + Align - 1) & ~(Align - 1))
0087     {
0088     }
0089 
0090     constexpr operator size_t() const noexcept { return myValue; }
0091   };
0092 
0093   //! A pointer aligned to a 4 byte boundary
0094   class AlignedPtr
0095   {
0096     uint8_t* myValue;
0097 
0098   public:
0099     constexpr AlignedPtr() noexcept
0100         : myValue(nullptr)
0101     {
0102     }
0103 
0104     AlignedPtr(void* const theValue) noexcept
0105         : myValue((uint8_t*)((size_t)theValue & ~(Align - 1)))
0106     {
0107     }
0108 
0109     operator void*() const noexcept { return myValue; }
0110 
0111     operator uint8_t*() const noexcept { return myValue; }
0112 
0113     AlignedPtr operator-(const AlignedSize theValue) const noexcept { return myValue - theValue; }
0114 
0115     AlignedPtr operator+(const AlignedSize theValue) const noexcept { return myValue + theValue; }
0116 
0117     AlignedPtr operator-=(const AlignedSize theValue) noexcept { return myValue -= theValue; }
0118 
0119     AlignedPtr operator+=(const AlignedSize theValue) noexcept { return myValue += theValue; }
0120   };
0121 
0122   //! A key for the map of blocks
0123   struct Key
0124   {
0125     size_t Value;
0126   };
0127 
0128   //! Key hasher
0129   class Hasher
0130   {
0131   public:
0132     //! Returns hash code for the given key
0133     //! @param theKey the key which hash code is to be computed
0134     //! @return a computed hash code
0135     size_t operator()(const Key theKey) const noexcept { return theKey.Value; }
0136 
0137     bool operator()(const Key theKey1, const Key theKey2) const noexcept
0138     {
0139       return theKey1.Value == theKey2.Value;
0140     }
0141   };
0142 
0143   //! Descriptor of a block
0144   struct Block
0145   {
0146     void*      address;
0147     AlignedPtr allocStart;
0148     Block*     prevBlock;
0149     int        allocCount;
0150 
0151     Block(void* const theAddress, const size_t theSize, Block* thePrevBlock = nullptr) noexcept
0152         : address(theAddress),
0153           prevBlock(thePrevBlock),
0154           allocCount(0)
0155     {
0156       SetFreeSize(theSize);
0157     }
0158 
0159     void SetFreeSize(const size_t theSize) noexcept { allocStart = (uint8_t*)address + theSize; }
0160 
0161     size_t FreeSize() const noexcept { return (uint8_t*)allocStart - (uint8_t*)address; }
0162 
0163     AlignedPtr Allocate(const AlignedSize theSize) noexcept
0164     {
0165       allocCount++;
0166       return allocStart -= theSize;
0167     }
0168 
0169     void Free() { allocCount--; }
0170 
0171     bool IsEmpty() const noexcept { return allocCount == 0; }
0172   };
0173 
0174   // --------- PROTECTED METHODS ---------
0175 protected:
0176   //! Calculate a key for the data map basing on the given address
0177   inline Key getKey(void* const theAddress) const noexcept
0178   {
0179     Key aKey = {(size_t)theAddress / myBlockSize};
0180     return aKey;
0181   }
0182 
0183   //! Find a block that the given allocation unit belongs to
0184   Standard_EXPORT Block* findBlock(void* const theAddress, Key& theKey) noexcept;
0185 
0186   //! Allocate a new block and return a pointer to it
0187   Standard_EXPORT Block* allocateNewBlock(const size_t theSize);
0188 
0189   // --------- PROHIBITED METHODS ---------
0190 private:
0191   NCollection_AccAllocator(const NCollection_AccAllocator&)            = delete;
0192   NCollection_AccAllocator& operator=(const NCollection_AccAllocator&) = delete;
0193 
0194   // --------- PROTECTED DATA ---------
0195 protected:
0196   AlignedSize                             myBlockSize;
0197   Block*                                  mypLastBlock;
0198   NCollection_DataMap<Key, Block, Hasher> myBlocks;
0199 
0200   // Declaration of CASCADE RTTI
0201 public:
0202   DEFINE_STANDARD_RTTIEXT(NCollection_AccAllocator, NCollection_BaseAllocator)
0203 };
0204 
0205 // Definition of HANDLE object using Standard_DefineHandle.hxx
0206 #endif