BuddyAllocatorBuilder.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  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. #pragma once
  6. #include <AnKi/Util/DynamicArray.h>
  7. namespace anki {
  8. /// @addtogroup util_memory
  9. /// @{
  10. /// @memberof BuddyAllocatorBuilder
  11. class BuddyAllocatorBuilderStats
  12. {
  13. public:
  14. PtrSize m_userAllocatedSize;
  15. PtrSize m_realAllocatedSize;
  16. F32 m_externalFragmentation;
  17. F32 m_internalFragmentation;
  18. };
  19. /// This is a generic implementation of a buddy allocator.
  20. /// @tparam kMaxMemoryRangeLog2 The max memory to allocate.
  21. /// @tparam TLock This an optional lock. Can be a Mutex or SpinLock or some dummy class.
  22. /// @tparam TMemoryPool The type of the pool to be used in internal CPU allocations.
  23. template<U32 kMaxMemoryRangeLog2, typename TLock, typename TMemoryPool = SingletonMemoryPoolWrapper<DefaultMemoryPool>>
  24. class BuddyAllocatorBuilder
  25. {
  26. public:
  27. /// The type of the address.
  28. using Address = std::conditional_t<(kMaxMemoryRangeLog2 > 32), PtrSize, U32>;
  29. using InternalMemoryPool = TMemoryPool;
  30. BuddyAllocatorBuilder()
  31. {
  32. }
  33. /// @copydoc init
  34. BuddyAllocatorBuilder(U32 maxMemoryRangeLog2, const TMemoryPool& pool = TMemoryPool())
  35. : m_freeLists(pool)
  36. {
  37. init(maxMemoryRangeLog2);
  38. }
  39. BuddyAllocatorBuilder(const BuddyAllocatorBuilder&) = delete; // Non-copyable
  40. ~BuddyAllocatorBuilder()
  41. {
  42. destroy();
  43. }
  44. BuddyAllocatorBuilder& operator=(const BuddyAllocatorBuilder&) = delete; // Non-copyable
  45. /// Init the allocator.
  46. /// @param maxMemoryRangeLog2 The max memory to allocate.
  47. void init(U32 maxMemoryRangeLog2);
  48. /// Destroy the allocator.
  49. void destroy();
  50. /// Allocate memory.
  51. /// @param size The size of the allocation.
  52. /// @param alignment The returned address should have this alignment.
  53. /// @param[out] address The returned address if the allocation didn't fail. It will stay untouched if it failed.
  54. /// @return True if the allocation succeeded.
  55. [[nodiscard]] Bool allocate(PtrSize size, PtrSize alignment, Address& address);
  56. /// Free memory.
  57. /// @param address The address to free.
  58. /// @param alignment The alignment of the original allocation.
  59. /// @param size The size of the allocation.
  60. void free(Address address, PtrSize size, PtrSize alignment);
  61. /// Print a debug representation of the internal structures.
  62. void debugPrint() const;
  63. /// Get some info.
  64. void getStats(BuddyAllocatorBuilderStats& stats) const;
  65. private:
  66. template<typename T>
  67. static constexpr T pow2(T exp)
  68. {
  69. return T(1) << exp;
  70. }
  71. static constexpr U32 log2(PtrSize v)
  72. {
  73. ANKI_ASSERT(isPowerOfTwo(v));
  74. return U32(std::countr_zero(v));
  75. }
  76. using FreeList = DynamicArray<Address, TMemoryPool, PtrSize>;
  77. DynamicArray<FreeList, TMemoryPool, U32> m_freeLists;
  78. PtrSize m_maxMemoryRange = 0;
  79. PtrSize m_userAllocatedSize = 0; ///< The total ammount of memory requested by the user.
  80. PtrSize m_realAllocatedSize = 0; ///< The total ammount of memory actually allocated.
  81. mutable TLock m_mutex;
  82. U32 orderCount() const
  83. {
  84. return m_freeLists.getSize();
  85. }
  86. PtrSize popFree(U32 order)
  87. {
  88. ANKI_ASSERT(m_freeLists[order].getSize() > 0);
  89. const PtrSize address = m_freeLists[order].getBack();
  90. m_freeLists[order].popBack();
  91. ANKI_ASSERT(address < m_maxMemoryRange);
  92. return address;
  93. }
  94. void freeInternal(PtrSize address, PtrSize size);
  95. TMemoryPool& getMemoryPool()
  96. {
  97. return m_freeLists.getMemoryPool();
  98. }
  99. };
  100. /// @}
  101. } // end namespace anki
  102. #include <AnKi/Util/BuddyAllocatorBuilder.inl.h>