GrMemoryPool.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. /*
  2. * Copyright 2012 Google Inc.
  3. *
  4. * Use of this source code is governed by a BSD-style license that can be
  5. * found in the LICENSE file.
  6. */
  7. #ifndef GrMemoryPool_DEFINED
  8. #define GrMemoryPool_DEFINED
  9. #include "include/gpu/GrTypes.h"
  10. #include "include/core/SkRefCnt.h"
  11. #ifdef SK_DEBUG
  12. #include "include/private/SkTHash.h"
  13. #endif
  14. /**
  15. * Allocates memory in blocks and parcels out space in the blocks for allocation
  16. * requests. It is optimized for allocate / release speed over memory
  17. * efficiency. The interface is designed to be used to implement operator new
  18. * and delete overrides. All allocations are expected to be released before the
  19. * pool's destructor is called. Allocations will be 8-byte aligned.
  20. */
  21. class GrMemoryPool {
  22. public:
  23. /**
  24. * Prealloc size is the amount of space to allocate at pool creation
  25. * time and keep around until pool destruction. The min alloc size is
  26. * the smallest allowed size of additional allocations. Both sizes are
  27. * adjusted to ensure that:
  28. * 1. they are are 8-byte aligned
  29. * 2. minAllocSize >= kSmallestMinAllocSize
  30. * 3. preallocSize >= minAllocSize
  31. *
  32. * Both sizes is what the pool will end up allocating from the system, and
  33. * portions of the allocated memory is used for internal bookkeeping.
  34. */
  35. GrMemoryPool(size_t preallocSize, size_t minAllocSize);
  36. ~GrMemoryPool();
  37. /**
  38. * Allocates memory. The memory must be freed with release().
  39. */
  40. void* allocate(size_t size);
  41. /**
  42. * p must have been returned by allocate()
  43. */
  44. void release(void* p);
  45. /**
  46. * Returns true if there are no unreleased allocations.
  47. */
  48. bool isEmpty() const { return fTail == fHead && !fHead->fLiveCount; }
  49. /**
  50. * Returns the total allocated size of the GrMemoryPool minus any preallocated amount
  51. */
  52. size_t size() const { return fSize; }
  53. /**
  54. * Returns the preallocated size of the GrMemoryPool
  55. */
  56. size_t preallocSize() const { return fHead->fSize; }
  57. /**
  58. * Minimum value of minAllocSize constructor argument.
  59. */
  60. constexpr static size_t kSmallestMinAllocSize = 1 << 10;
  61. private:
  62. struct BlockHeader;
  63. static BlockHeader* CreateBlock(size_t size);
  64. static void DeleteBlock(BlockHeader* block);
  65. void validate();
  66. struct BlockHeader {
  67. #ifdef SK_DEBUG
  68. uint32_t fBlockSentinal; ///< known value to check for bad back pointers to blocks
  69. #endif
  70. BlockHeader* fNext; ///< doubly-linked list of blocks.
  71. BlockHeader* fPrev;
  72. int fLiveCount; ///< number of outstanding allocations in the
  73. ///< block.
  74. intptr_t fCurrPtr; ///< ptr to the start of blocks free space.
  75. intptr_t fPrevPtr; ///< ptr to the last allocation made
  76. size_t fFreeSize; ///< amount of free space left in the block.
  77. size_t fSize; ///< total allocated size of the block
  78. };
  79. static const uint32_t kAssignedMarker = 0xCDCDCDCD;
  80. static const uint32_t kFreedMarker = 0xEFEFEFEF;
  81. struct AllocHeader {
  82. #ifdef SK_DEBUG
  83. uint32_t fSentinal; ///< known value to check for memory stomping (e.g., (CD)*)
  84. int32_t fID; ///< ID that can be used to track down leaks by clients.
  85. #endif
  86. BlockHeader* fHeader; ///< pointer back to the block header in which an alloc resides
  87. };
  88. size_t fSize;
  89. size_t fMinAllocSize;
  90. BlockHeader* fHead;
  91. BlockHeader* fTail;
  92. #ifdef SK_DEBUG
  93. int fAllocationCnt;
  94. int fAllocBlockCnt;
  95. SkTHashSet<int32_t> fAllocatedIDs;
  96. #endif
  97. protected:
  98. enum {
  99. // We assume this alignment is good enough for everybody.
  100. kAlignment = 8,
  101. kHeaderSize = GrSizeAlignUp(sizeof(BlockHeader), kAlignment),
  102. kPerAllocPad = GrSizeAlignUp(sizeof(AllocHeader), kAlignment),
  103. };
  104. };
  105. class GrOp;
  106. // DDL TODO: for the DLL use case this could probably be the non-intrinsic-based style of
  107. // ref counting
  108. class GrOpMemoryPool : public SkRefCnt {
  109. public:
  110. GrOpMemoryPool(size_t preallocSize, size_t minAllocSize)
  111. : fMemoryPool(preallocSize, minAllocSize) {
  112. }
  113. template <typename Op, typename... OpArgs>
  114. std::unique_ptr<Op> allocate(OpArgs&&... opArgs) {
  115. char* mem = (char*) fMemoryPool.allocate(sizeof(Op));
  116. return std::unique_ptr<Op>(new (mem) Op(std::forward<OpArgs>(opArgs)...));
  117. }
  118. void* allocate(size_t size) {
  119. return fMemoryPool.allocate(size);
  120. }
  121. void release(std::unique_ptr<GrOp> op);
  122. bool isEmpty() const { return fMemoryPool.isEmpty(); }
  123. private:
  124. GrMemoryPool fMemoryPool;
  125. };
  126. #endif