b2BlockAllocator.cpp
上传用户:gb3593
上传日期:2022-01-07
资源大小:3028k
文件大小:5k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /*
  2. * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
  3. *
  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.
  17. */
  18. #include <Box2D/Common/b2BlockAllocator.h>
  19. #include <cstdlib>
  20. #include <climits>
  21. #include <cstring>
  22. #include <memory>
  23. int32 b2BlockAllocator::s_blockSizes[b2_blockSizes] = 
  24. {
  25. 16, // 0
  26. 32, // 1
  27. 64, // 2
  28. 96, // 3
  29. 128, // 4
  30. 160, // 5
  31. 192, // 6
  32. 224, // 7
  33. 256, // 8
  34. 320, // 9
  35. 384, // 10
  36. 448, // 11
  37. 512, // 12
  38. 640, // 13
  39. };
  40. uint8 b2BlockAllocator::s_blockSizeLookup[b2_maxBlockSize + 1];
  41. bool b2BlockAllocator::s_blockSizeLookupInitialized;
  42. struct b2Chunk
  43. {
  44. int32 blockSize;
  45. b2Block* blocks;
  46. };
  47. struct b2Block
  48. {
  49. b2Block* next;
  50. };
  51. b2BlockAllocator::b2BlockAllocator()
  52. {
  53. b2Assert(b2_blockSizes < UCHAR_MAX);
  54. m_chunkSpace = b2_chunkArrayIncrement;
  55. m_chunkCount = 0;
  56. m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));
  57. memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));
  58. memset(m_freeLists, 0, sizeof(m_freeLists));
  59. if (s_blockSizeLookupInitialized == false)
  60. {
  61. int32 j = 0;
  62. for (int32 i = 1; i <= b2_maxBlockSize; ++i)
  63. {
  64. b2Assert(j < b2_blockSizes);
  65. if (i <= s_blockSizes[j])
  66. {
  67. s_blockSizeLookup[i] = (uint8)j;
  68. }
  69. else
  70. {
  71. ++j;
  72. s_blockSizeLookup[i] = (uint8)j;
  73. }
  74. }
  75. s_blockSizeLookupInitialized = true;
  76. }
  77. }
  78. b2BlockAllocator::~b2BlockAllocator()
  79. {
  80. for (int32 i = 0; i < m_chunkCount; ++i)
  81. {
  82. b2Free(m_chunks[i].blocks);
  83. }
  84. b2Free(m_chunks);
  85. }
  86. void* b2BlockAllocator::Allocate(int32 size)
  87. {
  88. if (size == 0)
  89. return NULL;
  90. b2Assert(0 < size && size <= b2_maxBlockSize);
  91. int32 index = s_blockSizeLookup[size];
  92. b2Assert(0 <= index && index < b2_blockSizes);
  93. if (m_freeLists[index])
  94. {
  95. b2Block* block = m_freeLists[index];
  96. m_freeLists[index] = block->next;
  97. return block;
  98. }
  99. else
  100. {
  101. if (m_chunkCount == m_chunkSpace)
  102. {
  103. b2Chunk* oldChunks = m_chunks;
  104. m_chunkSpace += b2_chunkArrayIncrement;
  105. m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk));
  106. memcpy(m_chunks, oldChunks, m_chunkCount * sizeof(b2Chunk));
  107. memset(m_chunks + m_chunkCount, 0, b2_chunkArrayIncrement * sizeof(b2Chunk));
  108. b2Free(oldChunks);
  109. }
  110. b2Chunk* chunk = m_chunks + m_chunkCount;
  111. chunk->blocks = (b2Block*)b2Alloc(b2_chunkSize);
  112. #if defined(_DEBUG)
  113. memset(chunk->blocks, 0xcd, b2_chunkSize);
  114. #endif
  115. int32 blockSize = s_blockSizes[index];
  116. chunk->blockSize = blockSize;
  117. int32 blockCount = b2_chunkSize / blockSize;
  118. b2Assert(blockCount * blockSize <= b2_chunkSize);
  119. for (int32 i = 0; i < blockCount - 1; ++i)
  120. {
  121. b2Block* block = (b2Block*)((int8*)chunk->blocks + blockSize * i);
  122. b2Block* next = (b2Block*)((int8*)chunk->blocks + blockSize * (i + 1));
  123. block->next = next;
  124. }
  125. b2Block* last = (b2Block*)((int8*)chunk->blocks + blockSize * (blockCount - 1));
  126. last->next = NULL;
  127. m_freeLists[index] = chunk->blocks->next;
  128. ++m_chunkCount;
  129. return chunk->blocks;
  130. }
  131. }
  132. void b2BlockAllocator::Free(void* p, int32 size)
  133. {
  134. if (size == 0)
  135. {
  136. return;
  137. }
  138. b2Assert(0 < size && size <= b2_maxBlockSize);
  139. int32 index = s_blockSizeLookup[size];
  140. b2Assert(0 <= index && index < b2_blockSizes);
  141. #ifdef _DEBUG
  142. // Verify the memory address and size is valid.
  143. int32 blockSize = s_blockSizes[index];
  144. bool found = false;
  145. for (int32 i = 0; i < m_chunkCount; ++i)
  146. {
  147. b2Chunk* chunk = m_chunks + i;
  148. if (chunk->blockSize != blockSize)
  149. {
  150. b2Assert( (int8*)p + blockSize <= (int8*)chunk->blocks ||
  151. (int8*)chunk->blocks + b2_chunkSize <= (int8*)p);
  152. }
  153. else
  154. {
  155. if ((int8*)chunk->blocks <= (int8*)p && (int8*)p + blockSize <= (int8*)chunk->blocks + b2_chunkSize)
  156. {
  157. found = true;
  158. }
  159. }
  160. }
  161. b2Assert(found);
  162. memset(p, 0xfd, blockSize);
  163. #endif
  164. b2Block* block = (b2Block*)p;
  165. block->next = m_freeLists[index];
  166. m_freeLists[index] = block;
  167. }
  168. void b2BlockAllocator::Clear()
  169. {
  170. for (int32 i = 0; i < m_chunkCount; ++i)
  171. {
  172. b2Free(m_chunks[i].blocks);
  173. }
  174. m_chunkCount = 0;
  175. memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk));
  176. memset(m_freeLists, 0, sizeof(m_freeLists));
  177. }