fixalloc.cpp 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // fixalloc.cpp - implementation of fixed block allocator
  2. #include "stdafx.h"
  3. #include "fixalloc.h"
  4. #ifdef _DEBUG
  5. #undef THIS_FILE
  6. static char THIS_FILE[] = __FILE__;
  7. #define new DEBUG_NEW
  8. #endif
  9. /////////////////////////////////////////////////////////////////////////////
  10. // CFixedAlloc
  11. CFixedAlloc::CFixedAlloc(UINT nAllocSize, UINT nBlockSize)
  12. {
  13. ASSERT(nAllocSize >= sizeof(CNode));
  14. ASSERT(nBlockSize > 1);
  15. m_nAllocSize = nAllocSize;
  16. m_nBlockSize = nBlockSize;
  17. m_pNodeFree = NULL;
  18. m_pBlocks = NULL;
  19. InitializeCriticalSection(&m_protect);
  20. }
  21. CFixedAlloc::~CFixedAlloc()
  22. {
  23. #ifndef __BORLANDC__ // Close your eyes, and hang on... here come the leaks!
  24. FreeAll();
  25. DeleteCriticalSection(&m_protect);
  26. #endif
  27. }
  28. void CFixedAlloc::FreeAll()
  29. {
  30. EnterCriticalSection(&m_protect);
  31. m_pBlocks->FreeDataChain();
  32. m_pBlocks = NULL;
  33. m_pNodeFree = NULL;
  34. LeaveCriticalSection(&m_protect);
  35. }
  36. void* CFixedAlloc::Alloc()
  37. {
  38. EnterCriticalSection(&m_protect);
  39. if (m_pNodeFree == NULL)
  40. {
  41. CPlex* pNewBlock = NULL;
  42. TRY
  43. {
  44. // add another block
  45. pNewBlock = CPlex::Create(m_pBlocks, m_nBlockSize, m_nAllocSize);
  46. }
  47. CATCH_ALL(e)
  48. {
  49. LeaveCriticalSection(&m_protect);
  50. THROW_LAST();
  51. }
  52. END_CATCH_ALL
  53. // chain them into free list
  54. CNode* pNode = (CNode*)pNewBlock->data();
  55. // free in reverse order to make it easier to debug
  56. (BYTE*&)pNode += (m_nAllocSize * m_nBlockSize) - m_nAllocSize;
  57. for (int i = m_nBlockSize-1; i >= 0; i--, (BYTE*&)pNode -= m_nAllocSize)
  58. {
  59. pNode->pNext = m_pNodeFree;
  60. m_pNodeFree = pNode;
  61. }
  62. }
  63. ASSERT(m_pNodeFree != NULL); // we must have something
  64. // remove the first available node from the free list
  65. void* pNode = m_pNodeFree;
  66. m_pNodeFree = m_pNodeFree->pNext;
  67. LeaveCriticalSection(&m_protect);
  68. return pNode;
  69. }
  70. void CFixedAlloc::Free(void* p)
  71. {
  72. if (p != NULL)
  73. {
  74. EnterCriticalSection(&m_protect);
  75. // simply return the node to the free list
  76. CNode* pNode = (CNode*)p;
  77. pNode->pNext = m_pNodeFree;
  78. m_pNodeFree = pNode;
  79. LeaveCriticalSection(&m_protect);
  80. }
  81. }