Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:04:17

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 
0017 #ifndef NCollection_AccAllocator_HeaderFile
0018 #define NCollection_AccAllocator_HeaderFile
0019 
0020 #include <NCollection_BaseAllocator.hxx>
0021 #include <NCollection_DataMap.hxx>
0022 
0023 //!
0024 //! Class  NCollection_AccAllocator  -  accumulating  memory  allocator.  This
0025 //! class  allocates  memory on request returning the pointer to the allocated
0026 //! space.  The  allocation  units  are  grouped  in blocks requested from the
0027 //! system  as  required.  This  memory  is  returned  to  the system when all
0028 //! allocations in a block are freed.
0029 //! 
0030 //! By comparison with  the standard new() and malloc()  calls, this method is
0031 //! faster and consumes very small additional memory to maintain the heap.
0032 //! 
0033 //! By comparison with NCollection_IncAllocator,  this class requires some more
0034 //! additional memory  and a little more time for allocation and deallocation.
0035 //! Memory overhead for NCollection_IncAllocator is 12 bytes per block;
0036 //! average memory overhead for NCollection_AccAllocator is 28 bytes per block.
0037 //! 
0038 //! All pointers  returned by Allocate() are aligned to 4 byte boundaries.
0039 //! To  define  the size  of  memory  blocks  requested  from the OS,  use the
0040 //! parameter of the constructor (measured in bytes).
0041 
0042 class NCollection_AccAllocator : public NCollection_BaseAllocator
0043 {
0044 // --------- PUBLIC CONSTANTS ---------
0045 public:
0046   //! Alignment of all allocated objects: 4 bytes
0047   static const Standard_Size    Align            = 4;
0048 
0049   //! Default block size
0050   static const Standard_Size    DefaultBlockSize = 24600;
0051 
0052   //! Number of last blocks to check for free space
0053   static const Standard_Integer MaxLookupBlocks  = 16;
0054 
0055 // ---------- PUBLIC METHODS ----------
0056 public:
0057   //! Constructor
0058   Standard_EXPORT NCollection_AccAllocator(const size_t
0059                                            theBlockSize = DefaultBlockSize);
0060 
0061   //! Destructor
0062   Standard_EXPORT ~NCollection_AccAllocator();
0063 
0064   //! Allocate memory with given size
0065   Standard_EXPORT virtual void* Allocate  (const size_t theSize) Standard_OVERRIDE;
0066 
0067   //! Allocate memory with given size
0068   void* AllocateOptimal(const size_t theSize) Standard_OVERRIDE
0069   {
0070     return Allocate(theSize);
0071   }
0072 
0073   //! Free a previously allocated memory;
0074   //! memory is returned to the OS when all allocations in some block are freed
0075   Standard_EXPORT virtual void  Free      (void* theAddress) Standard_OVERRIDE;
0076 
0077 // --------- PROTECTED TYPES ---------
0078 protected:
0079   //! Size value aligned to a 4 byte boundary
0080   class AlignedSize
0081   {
0082     Standard_Size myValue;
0083   public:
0084     AlignedSize() : myValue(0) {}
0085     AlignedSize(const Standard_Size theValue)
0086       : myValue((theValue + Align - 1) & ~(Align - 1)) {}
0087     operator Standard_Size() const {return myValue;}
0088   };
0089 
0090   //! A pointer aligned to a 4 byte boundary
0091   class AlignedPtr
0092   {
0093     Standard_Byte* myValue;
0094   public:
0095     AlignedPtr() : myValue(0) {}
0096     AlignedPtr(const Standard_Address theValue)
0097       : myValue((Standard_Byte*)((Standard_Size)theValue & ~(Align - 1))) {}
0098     operator Standard_Address       () const {return myValue;}
0099     operator Standard_Byte*         () const {return myValue;}
0100     AlignedPtr operator -(const AlignedSize theValue) const
0101       {return myValue - theValue;}
0102     AlignedPtr operator +(const AlignedSize theValue) const
0103       {return myValue + theValue;}
0104     AlignedPtr operator -=(const AlignedSize theValue)
0105       {return myValue -= theValue;}
0106     AlignedPtr operator +=(const AlignedSize theValue)
0107       {return myValue += theValue;}
0108   };
0109 
0110   //! A key for the map of blocks
0111   struct Key {Standard_Size Value;};
0112 
0113   //! Key hasher
0114   class Hasher
0115   {
0116   public:
0117     //! Returns hash code for the given key
0118     //! @param theKey the key which hash code is to be computed
0119     //! @return a computed hash code
0120     size_t operator() (const Key theKey) const noexcept
0121     {
0122       return theKey.Value;
0123     }
0124 
0125     bool operator() (const Key theKey1, const Key theKey2) const noexcept
0126     {
0127       return theKey1.Value == theKey2.Value;
0128     }
0129   };
0130   
0131   //! Descriptor of a block
0132   struct Block
0133   {
0134     Standard_Address address;
0135     AlignedPtr       allocStart;
0136     Block*           prevBlock;
0137     Standard_Integer allocCount;
0138 
0139     Block(const Standard_Address theAddress,
0140           const Standard_Size    theSize,
0141           Block*                 thePrevBlock = 0L)
0142       : address(theAddress), prevBlock(thePrevBlock), allocCount(0)
0143       {SetFreeSize (theSize);}
0144 
0145     void SetFreeSize(const Standard_Size theSize)
0146       {allocStart = (Standard_Byte*)address + theSize;}
0147 
0148     Standard_Size FreeSize() const
0149       {return (Standard_Byte*)allocStart - (Standard_Byte*)address;}
0150 
0151     AlignedPtr Allocate(const AlignedSize theSize)
0152       {allocCount++; return allocStart -= theSize;}
0153 
0154     void Free()
0155       {allocCount--;}
0156 
0157     Standard_Boolean IsEmpty() const
0158       {return allocCount == 0;}
0159   };
0160 
0161 // --------- PROTECTED METHODS ---------
0162 protected:
0163   //! Calculate a key for the data map basing on the given address
0164   inline Key getKey(const Standard_Address theAddress) const
0165   {
0166     Key aKey = {(Standard_Size)theAddress / myBlockSize};
0167     return aKey;
0168   }
0169 
0170   //! Find a block that the given allocation unit belongs to
0171   Standard_EXPORT Block* findBlock(const Standard_Address theAddress, Key& theKey);
0172 
0173   //! Allocate a new block and return a pointer to it
0174   Standard_EXPORT Block* allocateNewBlock(const Standard_Size theSize);
0175 
0176 // --------- PROHIBITED METHODS ---------
0177 private:
0178   NCollection_AccAllocator (const NCollection_AccAllocator&);
0179   NCollection_AccAllocator& operator = (const NCollection_AccAllocator&);
0180 
0181 // --------- PROTECTED DATA ---------
0182 protected:
0183   AlignedSize myBlockSize;
0184   Block*      mypLastBlock;
0185   NCollection_DataMap<Key, Block, Hasher> myBlocks;
0186 
0187 // Declaration of CASCADE RTTI
0188 public:
0189   DEFINE_STANDARD_RTTIEXT(NCollection_AccAllocator,NCollection_BaseAllocator)
0190 };
0191 
0192 // Definition of HANDLE object using Standard_DefineHandle.hxx
0193 DEFINE_STANDARD_HANDLE (NCollection_AccAllocator, NCollection_BaseAllocator)
0194 
0195 
0196 #endif