SegregatedListsAllocatorBuilder.h 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  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/Array.h>
  7. #include <AnKi/Util/DynamicArray.h>
  8. #include <AnKi/Util/StringList.h>
  9. namespace anki {
  10. /// @addtogroup util_memory
  11. /// @{
  12. namespace detail {
  13. /// Free block.
  14. /// @memberof SegregatedListsAllocatorBuilder
  15. /// @internal
  16. class SegregatedListsAllocatorBuilderFreeBlock
  17. {
  18. public:
  19. PtrSize m_size = 0;
  20. PtrSize m_address = 0;
  21. };
  22. } // end namespace detail
  23. /// The base class for all user memory chunks of SegregatedListsAllocatorBuilder.
  24. /// @memberof SegregatedListsAllocatorBuilder
  25. template<typename TMemoryPool>
  26. class SegregatedListsAllocatorBuilderChunkBase
  27. {
  28. template<typename, typename, typename, typename>
  29. friend class SegregatedListsAllocatorBuilder;
  30. protected:
  31. SegregatedListsAllocatorBuilderChunkBase(const TMemoryPool& pool = TMemoryPool())
  32. : m_freeLists(pool)
  33. {
  34. }
  35. private:
  36. DynamicArray<DynamicArray<detail::SegregatedListsAllocatorBuilderFreeBlock, TMemoryPool>, TMemoryPool> m_freeLists;
  37. PtrSize m_totalSize = 0;
  38. PtrSize m_freeSize = 0;
  39. };
  40. /// It provides the tools to build allocators base on segregated lists and best fit.
  41. /// @tparam TChunk A user defined class that contains a memory chunk. It should inherit from SegregatedListsAllocatorBuilderChunkBase.
  42. /// @tparam TInterface The interface that contains the following members:
  43. /// @code
  44. /// /// The number of classes
  45. /// U32 getClassCount() const;
  46. /// /// Max size for each class.
  47. /// void getClassInfo(U32 idx, PtrSize& size) const;
  48. /// /// Allocates a new user defined chunk of memory.
  49. /// Error allocateChunk(TChunk*& newChunk, PtrSize& chunkSize);
  50. /// /// Deletes a chunk.
  51. /// void deleteChunk(TChunk* chunk);
  52. /// /// Get the min alignment that will be required.
  53. /// PtrSize getMinSizeAlignment() const;
  54. /// @endcode
  55. /// @tparam TLock User defined lock (eg Mutex).
  56. template<typename TChunk, typename TInterface, typename TLock, typename TMemoryPool>
  57. class SegregatedListsAllocatorBuilder
  58. {
  59. public:
  60. SegregatedListsAllocatorBuilder(const TMemoryPool& pool = TMemoryPool())
  61. : m_chunks(pool)
  62. {
  63. }
  64. ~SegregatedListsAllocatorBuilder();
  65. SegregatedListsAllocatorBuilder(const SegregatedListsAllocatorBuilder&) = delete;
  66. SegregatedListsAllocatorBuilder& operator=(const SegregatedListsAllocatorBuilder&) = delete;
  67. /// Allocate memory.
  68. /// @param size The size to allocate.
  69. /// @param alignment The alignment of the returned address. No need to be power of 2.
  70. /// @param[out] chunk The chunk that the memory belongs to.
  71. /// @param[out] offset The offset inside the chunk.
  72. /// @note This is thread safe.
  73. Error allocate(PtrSize size, PtrSize alignment, TChunk*& chunk, PtrSize& offset);
  74. /// Free memory.
  75. /// @param chunk The chunk the allocation belongs to.
  76. /// @param offset The memory offset inside the chunk.
  77. void free(TChunk* chunk, PtrSize offset, PtrSize size);
  78. /// Validate the internal structures. It's only used in testing.
  79. Error validate() const;
  80. /// Print debug info.
  81. void printFreeBlocks(StringList& strList) const;
  82. /// It's 1-(largestBlockOfFreeMemory/totalFreeMemory). 0.0 is no fragmentation, 1.0 is totally fragmented.
  83. [[nodiscard]] F32 computeExternalFragmentation(PtrSize baseSize = 1) const;
  84. /// Adam Sawicki metric. 0.0 is no fragmentation, 1.0 is totally fragmented.
  85. [[nodiscard]] F32 computeExternalFragmentationSawicki(PtrSize baseSize = 1) const;
  86. TLock& getLock() const
  87. {
  88. return m_lock;
  89. }
  90. TInterface& getInterface()
  91. {
  92. return m_interface;
  93. }
  94. private:
  95. using FreeBlock = detail::SegregatedListsAllocatorBuilderFreeBlock;
  96. using ChunksIterator = typename DynamicArray<TChunk*>::Iterator;
  97. TInterface m_interface; ///< The interface.
  98. DynamicArray<TChunk*, TMemoryPool> m_chunks;
  99. mutable TLock m_lock;
  100. TMemoryPool& getMemoryPool()
  101. {
  102. return m_chunks.getMemoryPool();
  103. }
  104. U32 findClass(PtrSize size, PtrSize alignment) const;
  105. /// Choose the best free block out of 2 given the allocation size and alignment.
  106. /// @return True if the block returned is the best candidate overall.
  107. static Bool chooseBestFit(PtrSize allocSize, PtrSize allocAlignment, FreeBlock* blockA, FreeBlock* blockB, FreeBlock*& bestBlock);
  108. /// Place a free block in one of the lists.
  109. void placeFreeBlock(PtrSize address, PtrSize size, ChunksIterator chunkIt);
  110. };
  111. /// @}
  112. } // end namespace anki
  113. #include <AnKi/Util/SegregatedListsAllocatorBuilder.inl.h>