Index: src/gpu/GrMemoryPool.h |
diff --git a/src/gpu/GrMemoryPool.h b/src/gpu/GrMemoryPool.h |
index 43826d354a134f8d7bcbf667e395cb2095194fd0..0cefd0f2238be7c6c09b9e472d1f42945e35c5cd 100644 |
--- a/src/gpu/GrMemoryPool.h |
+++ b/src/gpu/GrMemoryPool.h |
@@ -13,16 +13,23 @@ |
/** |
* Allocates memory in blocks and parcels out space in the blocks for allocation |
* requests. It is optimized for allocate / release speed over memory |
- * effeciency. The interface is designed to be used to implement operator new |
+ * efficiency. The interface is designed to be used to implement operator new |
* and delete overrides. All allocations are expected to be released before the |
* pool's destructor is called. Allocations will be 8-byte aligned. |
*/ |
class GrMemoryPool { |
public: |
/** |
- * Prealloc size is the amount of space to make available at pool creation |
- * time and keep around until pool destruction. The min alloc size is the |
- * smallest allowed size of additional allocations. |
+ * Prealloc size is the amount of space to allocate at pool creation |
+ * time and keep around until pool destruction. The min alloc size is |
+ * the smallest allowed size of additional allocations. Both sizes are |
+ * adjusted to ensure that: |
+ * 1. they are are 8-byte aligned |
+ * 2. minAllocSize >= kSmallestMinAllocSize |
+ * 3. preallocSize >= minAllocSize |
+ * |
+ * Both sizes is what the pool will end up allocating from the system, and |
+ * portions of the allocated memory is used for internal bookkeeping. |
*/ |
GrMemoryPool(size_t preallocSize, size_t minAllocSize); |
@@ -48,6 +55,16 @@ public: |
*/ |
size_t size() const { return fSize; } |
+ /** |
+ * Returns the preallocated size of the GrMemoryPool |
+ */ |
+ size_t preallocSize() const { return fHead->fSize; } |
+ |
+ /** |
+ * Minimum value of minAllocSize constructor argument. |
+ */ |
+ constexpr static size_t kSmallestMinAllocSize = 1 << 10; |
+ |
private: |
struct BlockHeader; |
@@ -88,7 +105,6 @@ private: |
kPerAllocPad = GR_CT_ALIGN_UP(sizeof(AllocHeader), kAlignment), |
}; |
size_t fSize; |
- size_t fPreallocSize; |
size_t fMinAllocSize; |
BlockHeader* fHead; |
BlockHeader* fTail; |
@@ -96,6 +112,75 @@ private: |
int fAllocationCnt; |
int fAllocBlockCnt; |
#endif |
+ |
+ template <class T> |
+ friend class GrObjectMemoryPool; |
bsalomon
2016/11/28 16:03:31
Could this friendship go away if we moved some mor
DmitrySkiba
2016/11/29 01:08:02
Done.
|
}; |
+/** |
+ * Variant of GrMemoryPool that can only allocate objects of a single type. It is |
+ * not as flexible as GrMemoryPool, but it has more convenient allocate() method, |
+ * and more importantly, it guarantees number of objects that are preallocated at |
+ * construction or when adding a new memory block. I.e. |
+ * |
+ * GrMemoryPool pool(3 * sizeof(T), 1000 * sizeof(T)); |
+ * pool.allocate(sizeof(T)); |
+ * pool.allocate(sizeof(T)); |
+ * pool.allocate(sizeof(T)); |
+ * |
+ * will preallocate 3 * sizeof(T) bytes and use some of those bytes for internal |
+ * structures. Because of that, last allocate() call will end up allocating a new |
+ * block of 1000 * sizeof(T) bytes. In contrast, |
+ * |
+ * GrObjectMemoryPool<T> pool(3, 1000); |
+ * pool.allocate(); |
+ * pool.allocate(); |
+ * pool.allocate(); |
+ * |
+ * guarantees to preallocate enough memory for 3 objects of sizeof(T), so last |
+ * allocate() will use preallocated memory and won't cause allocation of a new block. |
+ * |
+ * Same thing is true for the second (minAlloc) ctor argument: this class guarantees |
+ * that a newly added block will have enough space for 1000 objects of sizeof(T), while |
+ * GrMemoryPool does not. |
+ */ |
+template <class T> |
+class GrObjectMemoryPool: public GrMemoryPool { |
+public: |
+ /** |
+ * Preallocates memory for preallocCount objects, and sets new block size to be |
+ * enough to hold minAllocCount objects. |
+ */ |
+ GrObjectMemoryPool(size_t preallocCount, size_t minAllocCount) |
+ : GrMemoryPool(countToSize(preallocCount), |
+ countToSize(SkTMax(minAllocCount, kSmallestMinAllocCount))) { |
+ } |
+ |
+ /** |
+ * Allocates memory for an object, but doesn't construct or otherwise initialize it. |
+ * The memory must be freed with release(). |
+ */ |
+ T* allocate() { return static_cast<T*>(GrMemoryPool::allocate(sizeof(T))); } |
+ |
+private: |
+ constexpr static size_t kTotalObjectSize = |
+ kPerAllocPad + GR_CT_ALIGN_UP(sizeof(T), kAlignment); |
+ |
+ constexpr static size_t countToSize(size_t count) { |
bsalomon
2016/11/28 16:03:31
nit: we capitalize the first char of a class stati
DmitrySkiba
2016/11/29 01:08:02
Done.
|
+ return kHeaderSize + count * kTotalObjectSize; |
+ } |
+ |
+public: |
+ |
+ /** |
+ * Minimum value of minAllocCount constructor argument. |
+ */ |
+ constexpr static size_t kSmallestMinAllocCount = |
+ (GrMemoryPool::kSmallestMinAllocSize - kHeaderSize + kTotalObjectSize - 1) / |
+ kTotalObjectSize; |
+}; |
+ |
+template <class T> |
+constexpr size_t GrObjectMemoryPool<T>::kSmallestMinAllocCount; |
+ |
#endif |