ObjectAllocator.h 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright (C) 2009-2021, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Util/Array.h>
  7. namespace anki
  8. {
  9. /// @addtogroup util_containers
  10. /// @{
  11. /// A simple allocator for objects of similar types.
  12. /// @tparam T_OBJECT_SIZE The maximum size of the objects.
  13. /// @tparam T_OBJECT_ALIGNMENT The maximum alignment of the objects.
  14. /// @tparam T_OBJECTS_PER_CHUNK How much memory (in objects) will be allocated at once.
  15. /// @tparam TIndexType If T_OBJECTS_PER_CHUNK>0xFF make it U16. If T_OBJECTS_PER_CHUNK>0xFFFF make it U32.
  16. template<PtrSize T_OBJECT_SIZE, U32 T_OBJECT_ALIGNMENT, U32 T_OBJECTS_PER_CHUNK = 64, typename TIndexType = U8>
  17. class ObjectAllocator
  18. {
  19. public:
  20. static constexpr PtrSize OBJECT_SIZE = T_OBJECT_SIZE;
  21. static constexpr U32 OBJECT_ALIGNMENT = T_OBJECT_ALIGNMENT;
  22. static constexpr U32 OBJECTS_PER_CHUNK = T_OBJECTS_PER_CHUNK;
  23. ObjectAllocator()
  24. {
  25. }
  26. ~ObjectAllocator()
  27. {
  28. ANKI_ASSERT(m_chunksHead == nullptr && m_chunksTail == nullptr && "Forgot to deallocate");
  29. }
  30. /// Allocate and construct a new object instance.
  31. /// @note Not thread-safe.
  32. template<typename T, typename TAlloc, typename... TArgs>
  33. T* newInstance(TAlloc& alloc, TArgs&&... args);
  34. /// Delete an object.
  35. /// @note Not thread-safe.
  36. template<typename T, typename TAlloc>
  37. void deleteInstance(TAlloc& alloc, T* obj);
  38. private:
  39. /// Storage with equal properties as the object.
  40. struct alignas(OBJECT_ALIGNMENT) Object
  41. {
  42. U8 m_storage[OBJECT_SIZE];
  43. };
  44. /// A single allocation.
  45. class Chunk
  46. {
  47. public:
  48. Array<Object, OBJECTS_PER_CHUNK> m_objects;
  49. Array<U32, OBJECTS_PER_CHUNK> m_unusedStack;
  50. U32 m_unusedCount;
  51. Chunk* m_next = nullptr;
  52. Chunk* m_prev = nullptr;
  53. };
  54. Chunk* m_chunksHead = nullptr;
  55. Chunk* m_chunksTail = nullptr;
  56. };
  57. /// Convenience wrapper for ObjectAllocator.
  58. template<typename T, U32 T_OBJECTS_PER_CHUNK = 64, typename TIndexType = U8>
  59. class ObjectAllocatorSameType : public ObjectAllocator<sizeof(T), U32(alignof(T)), T_OBJECTS_PER_CHUNK, TIndexType>
  60. {
  61. public:
  62. using Base = ObjectAllocator<sizeof(T), U32(alignof(T)), T_OBJECTS_PER_CHUNK, TIndexType>;
  63. /// Allocate and construct a new object instance.
  64. /// @note Not thread-safe.
  65. template<typename TAlloc, typename... TArgs>
  66. T* newInstance(TAlloc& alloc, TArgs&&... args)
  67. {
  68. return Base::template newInstance<T>(alloc, std::forward(args)...);
  69. }
  70. /// Delete an object.
  71. /// @note Not thread-safe.
  72. template<typename TAlloc>
  73. void deleteInstance(TAlloc& alloc, T* obj)
  74. {
  75. Base::deleteInstance(alloc, obj);
  76. }
  77. };
  78. /// @}
  79. } // end namespace anki
  80. #include <AnKi/Util/ObjectAllocator.inl.h>