ObjectAllocator.inl.h 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Util/ObjectAllocator.h>
  6. namespace anki {
  7. template<PtrSize kTObjectSize, U32 kTObjectAlignment, typename TMemoryPool, U32 kTObjectsPerChunk, typename TIndexType>
  8. template<typename T, typename... TArgs>
  9. T* ObjectAllocator<kTObjectSize, kTObjectAlignment, TMemoryPool, kTObjectsPerChunk, TIndexType>::newInstance(TArgs&&... args)
  10. {
  11. static_assert(alignof(T) <= kObjectAlignment, "Wrong object alignment");
  12. static_assert(sizeof(T) <= kObjectSize, "Wrong object size");
  13. T* out = nullptr;
  14. // Try find one in the chunks
  15. Chunk* chunk = m_chunksHead;
  16. while(chunk)
  17. {
  18. if(chunk->m_unusedCount > 0)
  19. {
  20. // Pop an element
  21. --chunk->m_unusedCount;
  22. out = reinterpret_cast<T*>(&chunk->m_objects[chunk->m_unusedStack[chunk->m_unusedCount]]);
  23. break;
  24. }
  25. chunk = chunk->m_next;
  26. }
  27. if(out == nullptr)
  28. {
  29. // Need to create a new chunk
  30. // Create the chunk
  31. chunk = anki::newInstance<Chunk>(m_pool);
  32. chunk->m_unusedCount = kObjectsPerChunk;
  33. for(U32 i = 0; i < kObjectsPerChunk; ++i)
  34. {
  35. chunk->m_unusedStack[i] = kObjectsPerChunk - (i + 1);
  36. }
  37. if(m_chunksTail)
  38. {
  39. ANKI_ASSERT(m_chunksHead);
  40. chunk->m_prev = m_chunksTail;
  41. m_chunksTail->m_next = chunk;
  42. m_chunksTail = chunk;
  43. }
  44. else
  45. {
  46. m_chunksTail = m_chunksHead = chunk;
  47. }
  48. // Allocate one object
  49. out = reinterpret_cast<T*>(&chunk->m_objects[0]);
  50. --chunk->m_unusedCount;
  51. }
  52. ANKI_ASSERT(out);
  53. // Construct it
  54. callConstructor(*out, std::forward<TArgs>(args)...);
  55. return out;
  56. }
  57. template<PtrSize kTObjectSize, U32 kTObjectAlignment, typename TMemoryPool, U32 kTObjectsPerChunk, typename TIndexType>
  58. template<typename T>
  59. void ObjectAllocator<kTObjectSize, kTObjectAlignment, TMemoryPool, kTObjectsPerChunk, TIndexType>::deleteInstance(T* obj)
  60. {
  61. static_assert(alignof(T) <= kObjectAlignment, "Wrong object alignment");
  62. static_assert(sizeof(T) <= kObjectSize, "Wrong object size");
  63. ANKI_ASSERT(obj);
  64. // Find the chunk the obj is in
  65. const Object* const mem = reinterpret_cast<Object*>(obj);
  66. Chunk* chunk = m_chunksHead;
  67. while(chunk)
  68. {
  69. const Object* const begin = chunk->m_objects.getBegin();
  70. const Object* const end = chunk->m_objects.getEnd();
  71. if(mem >= begin && mem < end)
  72. {
  73. // Found it, remove it from the chunk and maybe delete the chunk
  74. ANKI_ASSERT(chunk->m_unusedCount < kObjectsPerChunk);
  75. const U32 idx = U32(mem - begin);
  76. // Destroy the object
  77. callDestructor(*obj);
  78. // Remove from the chunk
  79. chunk->m_unusedStack[chunk->m_unusedCount] = idx;
  80. ++chunk->m_unusedCount;
  81. // Delete the chunk if it's empty
  82. if(chunk->m_unusedCount == kObjectsPerChunk)
  83. {
  84. if(chunk == m_chunksTail)
  85. {
  86. m_chunksTail = chunk->m_prev;
  87. }
  88. if(chunk == m_chunksHead)
  89. {
  90. m_chunksHead = chunk->m_next;
  91. }
  92. if(chunk->m_prev)
  93. {
  94. ANKI_ASSERT(chunk->m_prev->m_next == chunk);
  95. chunk->m_prev->m_next = chunk->m_next;
  96. }
  97. if(chunk->m_next)
  98. {
  99. ANKI_ASSERT(chunk->m_next->m_prev == chunk);
  100. chunk->m_next->m_prev = chunk->m_prev;
  101. }
  102. anki::deleteInstance(m_pool, chunk);
  103. }
  104. break;
  105. }
  106. chunk = chunk->m_next;
  107. }
  108. ANKI_ASSERT(chunk != nullptr);
  109. }
  110. } // end namespace anki