2 * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
4 * This software is provided 'as-is', without any express or implied
5 * warranty. In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 * 1. The origin of this software must not be misrepresented; you must not
11 * claim that you wrote the original software. If you use this software
12 * in a product, an acknowledgment in the product documentation would be
13 * appreciated but is not required.
14 * 2. Altered source versions must be plainly marked as such, and must not be
15 * misrepresented as being the original software.
16 * 3. This notice may not be removed or altered from any source distribution.
19 #include "b2BlockAllocator.h"
25 int32 b2BlockAllocator::s_blockSizes[b2_blockSizes] =
42 uint8 b2BlockAllocator::s_blockSizeLookup[b2_maxBlockSize + 1];
43 bool b2BlockAllocator::s_blockSizeLookupInitialized;
56 b2BlockAllocator::b2BlockAllocator()
58 b2Assert(b2_blockSizes < UCHAR_MAX);
60 m_chunkSpace = b2_chunkArrayIncrement;
62 m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));
64 memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));
65 memset(m_freeLists, 0, sizeof(m_freeLists));
67 if (s_blockSizeLookupInitialized == false)
70 for (int32 i = 1; i <= b2_maxBlockSize; ++i)
72 b2Assert(j < b2_blockSizes);
73 if (i <= s_blockSizes[j])
75 s_blockSizeLookup[i] = (uint8)j;
80 s_blockSizeLookup[i] = (uint8)j;
84 s_blockSizeLookupInitialized = true;
88 b2BlockAllocator::~b2BlockAllocator()
90 for (int32 i = 0; i < m_chunkCount; ++i)
92 b2Free(m_chunks[i].blocks);
98 void* b2BlockAllocator::Allocate(int32 size)
103 b2Assert(0 < size && size <= b2_maxBlockSize);
105 int32 index = s_blockSizeLookup[size];
106 b2Assert(0 <= index && index < b2_blockSizes);
108 if (m_freeLists[index])
110 b2Block* block = m_freeLists[index];
111 m_freeLists[index] = block->next;
116 if (m_chunkCount == m_chunkSpace)
118 b2Chunk* oldChunks = m_chunks;
119 m_chunkSpace += b2_chunkArrayIncrement;
120 m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));
121 memcpy(m_chunks, oldChunks, m_chunkCount * sizeof(b2Chunk));
122 memset(m_chunks + m_chunkCount, 0, b2_chunkArrayIncrement * sizeof(b2Chunk));
126 b2Chunk* chunk = m_chunks + m_chunkCount;
127 chunk->blocks = (b2Block*)b2Alloc(b2_chunkSize);
129 memset(chunk->blocks, 0xcd, b2_chunkSize);
131 int32 blockSize = s_blockSizes[index];
132 chunk->blockSize = blockSize;
133 int32 blockCount = b2_chunkSize / blockSize;
134 b2Assert(blockCount * blockSize <= b2_chunkSize);
135 for (int32 i = 0; i < blockCount - 1; ++i)
137 b2Block* block = (b2Block*)((int8*)chunk->blocks + blockSize * i);
138 b2Block* next = (b2Block*)((int8*)chunk->blocks + blockSize * (i + 1));
141 b2Block* last = (b2Block*)((int8*)chunk->blocks + blockSize * (blockCount - 1));
144 m_freeLists[index] = chunk->blocks->next;
147 return chunk->blocks;
151 void b2BlockAllocator::Free(void* p, int32 size)
158 b2Assert(0 < size && size <= b2_maxBlockSize);
160 int32 index = s_blockSizeLookup[size];
161 b2Assert(0 <= index && index < b2_blockSizes);
164 // Verify the memory address and size is valid.
165 int32 blockSize = s_blockSizes[index];
167 int32 gap = (int32)((int8*)&m_chunks->blocks - (int8*)m_chunks);
168 for (int32 i = 0; i < m_chunkCount; ++i)
170 b2Chunk* chunk = m_chunks + i;
171 if (chunk->blockSize != blockSize)
173 b2Assert( (int8*)p + blockSize <= (int8*)chunk->blocks ||
174 (int8*)chunk->blocks + b2_chunkSize + gap <= (int8*)p);
178 if ((int8*)chunk->blocks <= (int8*)p && (int8*)p + blockSize <= (int8*)chunk->blocks + b2_chunkSize)
187 memset(p, 0xfd, blockSize);
190 b2Block* block = (b2Block*)p;
191 block->next = m_freeLists[index];
192 m_freeLists[index] = block;
195 void b2BlockAllocator::Clear()
197 for (int32 i = 0; i < m_chunkCount; ++i)
199 b2Free(m_chunks[i].blocks);
203 memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));
205 memset(m_freeLists, 0, sizeof(m_freeLists));