Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-15 08:24:38

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 size  of  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 const Standard_Size Align = 4;
0047 
0048   //! Default block size
0049   static const Standard_Size DefaultBlockSize = 24600;
0050 
0051   //! Number of last blocks to check for free space
0052   static const Standard_Integer 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();
0061 
0062   //! Allocate memory with given size
0063   Standard_EXPORT virtual void* Allocate(const size_t theSize) Standard_OVERRIDE;
0064 
0065   //! Allocate memory with given size
0066   void* AllocateOptimal(const size_t theSize) Standard_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 virtual void Free(void* theAddress) Standard_OVERRIDE;
0071 
0072   // --------- PROTECTED TYPES ---------
0073 protected:
0074   //! Size value aligned to a 4 byte boundary
0075   class AlignedSize
0076   {
0077     Standard_Size myValue;
0078 
0079   public:
0080     AlignedSize()
0081         : myValue(0)
0082     {
0083     }
0084 
0085     AlignedSize(const Standard_Size theValue)
0086         : myValue((theValue + Align - 1) & ~(Align - 1))
0087     {
0088     }
0089 
0090     operator Standard_Size() const { return myValue; }
0091   };
0092 
0093   //! A pointer aligned to a 4 byte boundary
0094   class AlignedPtr
0095   {
0096     Standard_Byte* myValue;
0097 
0098   public:
0099     AlignedPtr()
0100         : myValue(0)
0101     {
0102     }
0103 
0104     AlignedPtr(const Standard_Address theValue)
0105         : myValue((Standard_Byte*)((Standard_Size)theValue & ~(Align - 1)))
0106     {
0107     }
0108 
0109     operator Standard_Address() const { return myValue; }
0110 
0111     operator Standard_Byte*() const { return myValue; }
0112 
0113     AlignedPtr operator-(const AlignedSize theValue) const { return myValue - theValue; }
0114 
0115     AlignedPtr operator+(const AlignedSize theValue) const { return myValue + theValue; }
0116 
0117     AlignedPtr operator-=(const AlignedSize theValue) { return myValue -= theValue; }
0118 
0119     AlignedPtr operator+=(const AlignedSize theValue) { return myValue += theValue; }
0120   };
0121 
0122   //! A key for the map of blocks
0123   struct Key
0124   {
0125     Standard_Size 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     Standard_Address address;
0147     AlignedPtr       allocStart;
0148     Block*           prevBlock;
0149     Standard_Integer allocCount;
0150 
0151     Block(const Standard_Address theAddress, const Standard_Size theSize, Block* thePrevBlock = 0L)
0152         : address(theAddress),
0153           prevBlock(thePrevBlock),
0154           allocCount(0)
0155     {
0156       SetFreeSize(theSize);
0157     }
0158 
0159     void SetFreeSize(const Standard_Size theSize)
0160     {
0161       allocStart = (Standard_Byte*)address + theSize;
0162     }
0163 
0164     Standard_Size FreeSize() const { return (Standard_Byte*)allocStart - (Standard_Byte*)address; }
0165 
0166     AlignedPtr Allocate(const AlignedSize theSize)
0167     {
0168       allocCount++;
0169       return allocStart -= theSize;
0170     }
0171 
0172     void Free() { allocCount--; }
0173 
0174     Standard_Boolean IsEmpty() const { return allocCount == 0; }
0175   };
0176 
0177   // --------- PROTECTED METHODS ---------
0178 protected:
0179   //! Calculate a key for the data map basing on the given address
0180   inline Key getKey(const Standard_Address theAddress) const
0181   {
0182     Key aKey = {(Standard_Size)theAddress / myBlockSize};
0183     return aKey;
0184   }
0185 
0186   //! Find a block that the given allocation unit belongs to
0187   Standard_EXPORT Block* findBlock(const Standard_Address theAddress, Key& theKey);
0188 
0189   //! Allocate a new block and return a pointer to it
0190   Standard_EXPORT Block* allocateNewBlock(const Standard_Size theSize);
0191 
0192   // --------- PROHIBITED METHODS ---------
0193 private:
0194   NCollection_AccAllocator(const NCollection_AccAllocator&);
0195   NCollection_AccAllocator& operator=(const NCollection_AccAllocator&);
0196 
0197   // --------- PROTECTED DATA ---------
0198 protected:
0199   AlignedSize                             myBlockSize;
0200   Block*                                  mypLastBlock;
0201   NCollection_DataMap<Key, Block, Hasher> myBlocks;
0202 
0203   // Declaration of CASCADE RTTI
0204 public:
0205   DEFINE_STANDARD_RTTIEXT(NCollection_AccAllocator, NCollection_BaseAllocator)
0206 };
0207 
0208 // Definition of HANDLE object using Standard_DefineHandle.hxx
0209 DEFINE_STANDARD_HANDLE(NCollection_AccAllocator, NCollection_BaseAllocator)
0210 
0211 #endif