Flutter Engine
The Flutter Engine
Classes | Public Member Functions | Static Public Member Functions | Static Public Attributes | List of all members
GrMemoryPool Class Reference

#include <GrMemoryPool.h>

Public Member Functions

 ~GrMemoryPool ()
 
void operator delete (void *p)
 
void * allocate (size_t size)
 
void release (void *p)
 
bool isEmpty () const
 
void reportLeaks () const
 
size_t size () const
 
size_t preallocSize () const
 
void resetScratchSpace ()
 

Static Public Member Functions

static std::unique_ptr< GrMemoryPoolMake (size_t preallocSize, size_t minAllocSize)
 

Static Public Attributes

static constexpr size_t kAlignment = alignof(std::max_align_t)
 
static constexpr size_t kMinAllocationSize = 1 << 10
 

Detailed Description

Allocates memory in blocks and parcels out space in the blocks for allocation requests. It is optimized for allocate / release speed over memory 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 aligned to sizeof(std::max_align_t).

All allocated objects must be released back to the memory pool before it can be destroyed.

Definition at line 31 of file GrMemoryPool.h.

Constructor & Destructor Documentation

◆ ~GrMemoryPool()

GrMemoryPool::~GrMemoryPool ( )

Definition at line 43 of file GrMemoryPool.cpp.

43 {
44 this->reportLeaks();
45 SkASSERT(0 == fDebug->fAllocationCount);
46 SkASSERT(this->isEmpty());
47 SkDEBUGCODE(delete fDebug;)
48}
#define SkASSERT(cond)
Definition: SkAssert.h:116
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
void reportLeaks() const
bool isEmpty() const
Definition: GrMemoryPool.h:73

Member Function Documentation

◆ allocate()

void * GrMemoryPool::allocate ( size_t  size)

Allocates memory. The memory must be freed with release() before the GrMemoryPool is deleted.

Definition at line 67 of file GrMemoryPool.cpp.

67 {
68 static_assert(alignof(Header) <= kAlignment);
69 SkDEBUGCODE(this->validate();)
70
71 SkBlockAllocator::ByteRange alloc = fAllocator.allocate<kAlignment, sizeof(Header)>(size);
72
73 // Initialize GrMemoryPool's custom header at the start of the allocation
74 Header* header = static_cast<Header*>(alloc.fBlock->ptr(alloc.fAlignedOffset - sizeof(Header)));
75 header->fStart = alloc.fStart;
76 header->fEnd = alloc.fEnd;
77
78 // Update live count within the block
79 alloc.fBlock->setMetadata(alloc.fBlock->metadata() + 1);
80
81#if defined(SK_SANITIZE_ADDRESS)
82 sk_asan_poison_memory_region(&header->fSentinel, sizeof(header->fSentinel));
83#elif defined(SK_DEBUG)
84 header->fSentinel = SkBlockAllocator::kAssignedMarker;
85#endif
86
87#if defined(SK_DEBUG)
88 header->fID = []{
89 static std::atomic<int> nextID{1};
90 return nextID.fetch_add(1, std::memory_order_relaxed);
91 }();
92
93 // You can set a breakpoint here when a leaked ID is allocated to see the stack frame.
94 fDebug->fAllocatedIDs.add(header->fID);
95 fDebug->fAllocationCount++;
96#endif
97
98 // User-facing pointer is after the header padding
99 return alloc.fBlock->ptr(alloc.fAlignedOffset);
100}
static void sk_asan_poison_memory_region(void const volatile *addr, size_t size)
Definition: SkASAN.h:34
static constexpr size_t kAlignment
Definition: GrMemoryPool.h:40
size_t size() const
Definition: GrMemoryPool.h:90
ByteRange allocate(size_t size)
static const char header[]
Definition: skpbench.cpp:88

◆ isEmpty()

bool GrMemoryPool::isEmpty ( ) const
inline

Returns true if there are no unreleased allocations.

Definition at line 73 of file GrMemoryPool.h.

73 {
74 // If size is the same as preallocSize, there aren't any heap blocks, so currentBlock()
75 // is the inline head block.
76 return fAllocator.currentBlock() == fAllocator.headBlock() &&
77 fAllocator.currentBlock()->metadata() == 0;
78 }
const Block * headBlock() const
const Block * currentBlock() const

◆ Make()

std::unique_ptr< GrMemoryPool > GrMemoryPool::Make ( size_t  preallocSize,
size_t  minAllocSize 
)
static

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 they are at least as large as kMinAllocationSize and less than SkBlockAllocator::kMaxAllocationSize.

Both sizes are what the pool will end up allocating from the system, and portions of the allocated memory is used for internal bookkeeping.

Definition at line 23 of file GrMemoryPool.cpp.

23 {
24 static_assert(sizeof(GrMemoryPool) < GrMemoryPool::kMinAllocationSize);
25
28 minAllocSize = SkTPin(minAllocSize, kMinAllocationSize,
30 void* mem = operator new(preallocSize);
31 return std::unique_ptr<GrMemoryPool>(new (mem) GrMemoryPool(preallocSize, minAllocSize));
32}
static constexpr const T & SkTPin(const T &x, const T &lo, const T &hi)
Definition: SkTPin.h:19
static constexpr size_t kMinAllocationSize
Definition: GrMemoryPool.h:44
size_t preallocSize() const
Definition: GrMemoryPool.h:95
static constexpr int kMaxAllocationSize

◆ operator delete()

void GrMemoryPool::operator delete ( void *  p)
inline

Definition at line 59 of file GrMemoryPool.h.

59{ ::operator delete(p); }

◆ preallocSize()

size_t GrMemoryPool::preallocSize ( ) const
inline

Returns the preallocated size of the GrMemoryPool

Definition at line 95 of file GrMemoryPool.h.

95 {
96 // Account for the debug-only fields in this count, the offset is 0 for release builds
98 return offsetof(GrMemoryPool, fAllocator) + fAllocator.preallocSize();
99 }
size_t preallocSize() const
uint8_t value

◆ release()

void GrMemoryPool::release ( void *  p)

p must have been returned by allocate().

Definition at line 102 of file GrMemoryPool.cpp.

102 {
103 Header* header = reinterpret_cast<Header*>(reinterpret_cast<intptr_t>(p) - sizeof(Header));
104
105#if defined(SK_SANITIZE_ADDRESS)
106 sk_asan_unpoison_memory_region(&header->fSentinel, sizeof(header->fSentinel));
107#elif defined(SK_DEBUG)
108 SkASSERT(SkBlockAllocator::kAssignedMarker == header->fSentinel);
109 header->fSentinel = SkBlockAllocator::kFreedMarker;
110#endif
111
112#if defined(SK_DEBUG)
113 fDebug->fAllocatedIDs.remove(header->fID);
114 fDebug->fAllocationCount--;
115#endif
116
117 SkBlockAllocator::Block* block = fAllocator.owningBlock<kAlignment>(header, header->fStart);
118
119#if defined(SK_DEBUG)
120 // (p - block) matches the original alignedOffset value from SkBlockAllocator::allocate().
121 intptr_t alignedOffset = (intptr_t)p - (intptr_t)block;
122 SkASSERT(p == block->ptr(alignedOffset));
123
124 // Scrub the block contents to prevent use-after-free errors.
125 memset(p, 0xDD, header->fEnd - alignedOffset);
126#endif
127
128 int alive = block->metadata();
129 if (alive == 1) {
130 // This was last allocation in the block, so remove it
131 fAllocator.releaseBlock(block);
132 } else {
133 // Update count and release storage of the allocation itself
134 block->setMetadata(alive - 1);
135 block->release(header->fStart, header->fEnd);
136 }
137}
static void sk_asan_unpoison_memory_region(void const volatile *addr, size_t size)
Definition: SkASAN.h:41
bool release(int start, int end)
void * ptr(int offset)
void setMetadata(int value)
void releaseBlock(Block *block)
Block * owningBlock(const void *ptr, int start)

◆ reportLeaks()

void GrMemoryPool::reportLeaks ( ) const

In debug mode, this reports the IDs of unfreed nodes via SkDebugf. This reporting is also performed automatically whenever a GrMemoryPool is destroyed. In release mode, this method is a no-op.

Definition at line 50 of file GrMemoryPool.cpp.

50 {
51#ifdef SK_DEBUG
52 int i = 0;
53 int n = fDebug->fAllocatedIDs.count();
54 for (int id : fDebug->fAllocatedIDs) {
55 if (++i == 1) {
56 SkDebugf("Leaked %d IDs (in no particular order): %d%s", n, id, (n == i) ? "\n" : "");
57 } else if (i < 11) {
58 SkDebugf(", %d%s", id, (n == i ? "\n" : ""));
59 } else if (i == 11) {
60 SkDebugf(", ...\n");
61 break;
62 }
63 }
64#endif
65}
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1

◆ resetScratchSpace()

void GrMemoryPool::resetScratchSpace ( )
inline

Frees any scratch blocks that are no longer being used.

Definition at line 104 of file GrMemoryPool.h.

104 {
105 fAllocator.resetScratchSpace();
106 }

◆ size()

size_t GrMemoryPool::size ( ) const
inline

Returns the total allocated size of the GrMemoryPool minus any preallocated amount

Definition at line 90 of file GrMemoryPool.h.

90{ return fAllocator.totalSize() - fAllocator.preallocSize(); }
size_t totalSize() const

Member Data Documentation

◆ kAlignment

constexpr size_t GrMemoryPool::kAlignment = alignof(std::max_align_t)
staticconstexpr

Definition at line 40 of file GrMemoryPool.h.

◆ kMinAllocationSize

constexpr size_t GrMemoryPool::kMinAllocationSize = 1 << 10
inlinestaticconstexpr

Definition at line 44 of file GrMemoryPool.h.


The documentation for this class was generated from the following files: