CmFrameAlloc.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. #include "CmFrameAlloc.h"
  2. #include "CmException.h"
  3. namespace CamelotFramework
  4. {
  5. FrameAlloc::MemBlock::MemBlock(UINT32 size)
  6. :mData(nullptr), mFreePtr(0), mSize(size)
  7. { }
  8. FrameAlloc::MemBlock::~MemBlock()
  9. { }
  10. UINT8* FrameAlloc::MemBlock::alloc(UINT8 amount)
  11. {
  12. UINT8* freePtr = &mData[mFreePtr];
  13. mFreePtr += amount;
  14. return freePtr;
  15. }
  16. void FrameAlloc::MemBlock::clear()
  17. {
  18. mFreePtr = 0;
  19. }
  20. FrameAlloc::FrameAlloc(UINT32 blockSize)
  21. :mTotalAllocBytes(0), mFreeBlock(nullptr), mBlockSize(blockSize)
  22. {
  23. allocBlock(mBlockSize);
  24. }
  25. FrameAlloc::~FrameAlloc()
  26. {
  27. for(auto& block : mBlocks)
  28. deallocBlock(block);
  29. }
  30. UINT8* FrameAlloc::alloc(UINT32 amount)
  31. {
  32. amount += sizeof(UINT32);
  33. UINT32 freeMem = mFreeBlock->mSize - mFreeBlock->mFreePtr;
  34. if(amount > freeMem)
  35. allocBlock(amount);
  36. UINT8* data = mFreeBlock->alloc(amount);
  37. mTotalAllocBytes += amount;
  38. UINT32* storedSize = reinterpret_cast<UINT32*>(data);
  39. *storedSize = amount;
  40. return data + sizeof(UINT32);
  41. }
  42. void FrameAlloc::dealloc(UINT8* data)
  43. {
  44. // Dealloc is only used for debug and can be removed if needed. All the actual deallocation
  45. // happens in "clear"
  46. data -= sizeof(UINT32);
  47. UINT32* storedSize = reinterpret_cast<UINT32*>(data);
  48. mTotalAllocBytes -= *storedSize;
  49. }
  50. void FrameAlloc::clear()
  51. {
  52. if(mTotalAllocBytes.load() > 0)
  53. CM_EXCEPT(InvalidStateException, "Not all frame allocated bytes were properly released.");
  54. // Merge all blocks into one
  55. UINT32 totalBytes = 0;
  56. for(auto& block : mBlocks)
  57. {
  58. totalBytes += block->mSize;
  59. deallocBlock(block);
  60. }
  61. mBlocks.clear();
  62. allocBlock(totalBytes);
  63. }
  64. FrameAlloc::MemBlock* FrameAlloc::allocBlock(UINT32 wantedSize)
  65. {
  66. UINT32 blockSize = mBlockSize;
  67. if(wantedSize > blockSize)
  68. blockSize = wantedSize;
  69. UINT8* data = (UINT8*)reinterpret_cast<UINT8*>(cm_alloc(blockSize + sizeof(MemBlock)));
  70. MemBlock* newBlock = new (data) MemBlock(blockSize);
  71. data += sizeof(MemBlock);
  72. newBlock->mData = data;
  73. mBlocks.push_back(newBlock);
  74. mFreeBlock = newBlock; // If previous block had some empty space it is lost until next "clear"
  75. return newBlock;
  76. }
  77. void FrameAlloc::deallocBlock(MemBlock* block)
  78. {
  79. block->~MemBlock();
  80. cm_free(block);
  81. }
  82. }