1 // File: NCollection_IncAllocator.cxx
2 // Created: 12.04.02 21:16:26
3 // Author: Alexander GRIGORIEV
4 // Copyright: Open Cascade 2002
6 #include <NCollection_IncAllocator.hxx>
7 #include <Standard_OutOfMemory.hxx>
10 IMPLEMENT_STANDARD_HANDLE (NCollection_IncAllocator,NCollection_BaseAllocator)
11 IMPLEMENT_STANDARD_RTTIEXT (NCollection_IncAllocator,NCollection_BaseAllocator)
13 #define IMEM_SIZE(_size) ((((_size) - 1)/sizeof(aligned_t)) + 1)
14 #define IMEM_FREE(p_bl) ((unsigned int)(p_bl->p_end_block - p_bl->p_free_space))
15 #define IMEM_ALIGN(_addr) (sizeof(aligned_t)* IMEM_SIZE((unsigned long)(_addr)))
19 //=======================================================================
20 //function : NCollection_IncAllocator()
21 //purpose : Constructor
22 //=======================================================================
24 NCollection_IncAllocator::NCollection_IncAllocator (const size_t theBlockSize)
26 #ifdef ALLOC_TRACK_USAGE
27 printf ("\n..NCollection_IncAllocator: Created (%x)\n",this);
29 const size_t aSize = IMEM_SIZE(sizeof(IBlock)) +
30 IMEM_SIZE((theBlockSize > 2*sizeof(IBlock)) ? theBlockSize : 24600);
31 IBlock * const aBlock = (IBlock *) malloc (aSize * sizeof(aligned_t));
32 myFirstBlock = aBlock;
35 Standard_OutOfMemory::Raise("NCollection_IncAllocator: out of memory");
36 aBlock -> p_free_space = (aligned_t *) IMEM_ALIGN (&aBlock[1]);
37 aBlock -> p_end_block = ((aligned_t *) aBlock) + aSize;
38 aBlock -> p_next = NULL;
41 //=======================================================================
42 //function : ~NCollection_IncAllocator
43 //purpose : Destructor
44 //=======================================================================
46 NCollection_IncAllocator::~NCollection_IncAllocator ()
52 //=======================================================================
54 //purpose : allocate a memory
55 //remark : returns NULL if allocation fails
56 //=======================================================================
58 void * NCollection_IncAllocator::Allocate (const size_t aSize)
60 aligned_t * aResult = NULL;
61 const size_t cSize = aSize ? IMEM_SIZE(aSize) : 0;
64 /* If the requested size exceeds normal allocation size, allocate
65 a separate block and place it as the head of the list */
66 aResult = (aligned_t *) allocateNewBlock (cSize+1);
68 myFirstBlock -> p_free_space = myFirstBlock -> p_end_block;
70 if (cSize <= IMEM_FREE(myFirstBlock)) {
71 /* If the requested size fits into the free space in the 1st block */
72 aResult = myFirstBlock -> allocateInBlock (cSize);
74 /* Search for a block in the list with enough free space */
75 int aMaxLookup = MaxLookup; /* limit the number of blocks to query */
76 IBlock * aCurrentBlock = myFirstBlock -> p_next;
77 while (aCurrentBlock && aMaxLookup--) {
78 if (cSize <= IMEM_FREE(aCurrentBlock)) {
79 aResult = aCurrentBlock -> allocateInBlock (cSize);
82 aCurrentBlock = aCurrentBlock -> p_next;
84 if (aResult == NULL) {
85 /* There is no available block with enough free space. Create a new
86 one and place it in the head of the list */
87 aResult = (aligned_t *) allocateNewBlock (mySize);
89 myFirstBlock -> p_free_space = aResult + cSize;
95 //=======================================================================
96 //function : Reallocate
98 //=======================================================================
100 void * NCollection_IncAllocator::Reallocate (void * theAddress,
101 const size_t oldSize,
102 const size_t newSize)
104 // Check that the dummy parameters are OK
105 if (theAddress == NULL || oldSize == 0)
106 return Allocate (newSize);
107 const size_t cOldSize = IMEM_SIZE(oldSize);
108 const size_t cNewSize = newSize ? IMEM_SIZE(newSize) : 0;
109 aligned_t * anAddress = (aligned_t *) theAddress;
111 // We check only the LAST allocation to do the real extension/contraction
112 if (anAddress + cOldSize == myFirstBlock -> p_free_space) {
113 myFirstBlock -> p_free_space = anAddress;
114 // If the new size fits into the memory block => OK
115 // This also includes any case of contraction
116 if (cNewSize <= IMEM_FREE(myFirstBlock)) {
117 myFirstBlock -> p_free_space += cNewSize;
121 // In case of contraction of non-terminating allocation, do nothing
122 else if (cOldSize >= cNewSize)
124 // Extension of non-terminated allocation if there is enough room in the
125 // current memory block
126 if (cNewSize <= IMEM_FREE(myFirstBlock)) {
127 aligned_t * aResult = myFirstBlock -> allocateInBlock (cNewSize);
129 for (unsigned i = 0; i < cOldSize; i++)
130 aResult[i] = anAddress[i];
134 // This is either of the cases:
135 // - extension of non-terminating allocation, or
136 // - extension of terminating allocation when the new size is too big
137 // In both cases create a new memory block, allocate memory and copy there
138 // the reallocated memory.
139 aligned_t * aResult = (aligned_t *) allocateNewBlock (mySize);
141 myFirstBlock -> p_free_space = aResult + cNewSize;
142 for (unsigned i = 0; i < cOldSize; i++)
143 aResult[i] = anAddress[i];
148 //=======================================================================
151 //=======================================================================
153 void NCollection_IncAllocator::Free (void *)
156 //=======================================================================
159 //=======================================================================
161 void NCollection_IncAllocator::Clean ()
163 #ifdef ALLOC_TRACK_USAGE
164 printf ("\n..NCollection_IncAllocator: Memory size to clean:%8.1f kB (%x)\n",
165 double(GetMemSize())/1024, this);
167 IBlock * aBlock = myFirstBlock;
169 aBlock -> p_free_space = (aligned_t *) &aBlock[1];
170 aBlock = aBlock -> p_next;
172 IBlock * aNext = aBlock -> p_next;
176 myFirstBlock -> p_next = NULL;
180 //=======================================================================
183 //=======================================================================
185 void NCollection_IncAllocator::Reset (const Standard_Boolean doReleaseMem)
190 Standard_Integer aBlockCount(0);
191 IBlock * aBlock = myFirstBlock;
193 if (aBlockCount++ < MaxLookup) {
194 aBlock -> p_free_space = (aligned_t *) &aBlock[1];
195 if (aBlockCount < MaxLookup)
196 aBlock = aBlock -> p_next;
198 IBlock * aNext = aBlock -> p_next;
199 aBlock -> p_next = NULL;
203 IBlock * aNext = aBlock -> p_next;
210 //=======================================================================
211 //function : GetMemSize
212 //purpose : diagnostic utility
213 //=======================================================================
215 size_t NCollection_IncAllocator::GetMemSize () const
218 IBlock * aBlock = myFirstBlock;
220 aResult += (aBlock -> p_end_block - (aligned_t *) aBlock);
221 aBlock = aBlock -> p_next;
223 return aResult * sizeof (aligned_t);
226 //=======================================================================
227 //function : allocateNewBlock
229 //=======================================================================
231 void * NCollection_IncAllocator::allocateNewBlock (const size_t cSize)
233 aligned_t * aResult = 0L;
234 const size_t aSz = cSize + IMEM_SIZE(sizeof(IBlock));
235 IBlock * aBlock = (IBlock *) malloc (aSz * sizeof(aligned_t));
237 aBlock -> p_end_block = ((aligned_t *)aBlock) + aSz;
238 aBlock -> p_next = myFirstBlock;
239 myFirstBlock = aBlock;
240 aResult = (aligned_t *) IMEM_ALIGN(&aBlock[1]);
243 Standard_OutOfMemory::Raise("NCollection_IncAllocator: out of memory");