*/
#include "GrMemoryPool.h"
-
#include "SkMalloc.h"
+#ifdef SK_DEBUG
+#include "SkAtomics.h"
+#endif
#ifdef SK_DEBUG
#define VALIDATE this->validate()
GrMemoryPool::~GrMemoryPool() {
VALIDATE;
+#ifdef SK_DEBUG
+ int i = 0;
+ int n = fAllocatedIDs.count();
+ fAllocatedIDs.foreach([&i, n] (int32_t id) {
+ if (++i == 1) {
+ SkDebugf("Leaked IDs (in no particular order): %d", id);
+ } else if (i < 11) {
+ SkDebugf(", %d%s", id, (n == i ? "\n" : ""));
+ } else if (i == 11) {
+ SkDebugf(", ...\n");
+ }
+ });
+#endif
SkASSERT(0 == fAllocationCnt);
SkASSERT(fHead == fTail);
SkASSERT(0 == fHead->fLiveCount);
// so that we can decrement the live count on delete in constant time.
AllocHeader* allocData = reinterpret_cast<AllocHeader*>(ptr);
SkDEBUGCODE(allocData->fSentinal = kAssignedMarker);
+ SkDEBUGCODE(allocData->fID = []{static int32_t gID; return sk_atomic_inc(&gID) + 1;}());
+ // You can set a breakpoint here when a leaked ID is allocated to see the stack frame.
+ SkDEBUGCODE(fAllocatedIDs.add(allocData->fID));
allocData->fHeader = fTail;
ptr += kPerAllocPad;
fTail->fPrevPtr = fTail->fCurrPtr;
fTail->fCurrPtr += size;
fTail->fFreeSize -= size;
fTail->fLiveCount += 1;
-
SkDEBUGCODE(++fAllocationCnt);
VALIDATE;
return reinterpret_cast<void*>(ptr);
AllocHeader* allocData = reinterpret_cast<AllocHeader*>(ptr);
SkASSERT(kAssignedMarker == allocData->fSentinal);
SkDEBUGCODE(allocData->fSentinal = kFreedMarker);
+ SkDEBUGCODE(fAllocatedIDs.remove(allocData->fID));
BlockHeader* block = allocData->fHeader;
SkASSERT(kAssignedMarker == block->fBlockSentinal);
if (1 == block->fLiveCount) {
prev = block;
} while ((block = block->fNext));
SkASSERT(allocCount == fAllocationCnt);
+ SkASSERT(fAllocationCnt == fAllocatedIDs.count());
SkASSERT(prev == fTail);
SkASSERT(fAllocBlockCnt != 0 || fSize == 0);
#endif
#define GrMemoryPool_DEFINED
#include "GrTypes.h"
+#ifdef SK_DEBUG
+#include "SkTHash.h"
+#endif
/**
* Allocates memory in blocks and parcels out space in the blocks for allocation
struct AllocHeader {
#ifdef SK_DEBUG
uint32_t fSentinal; ///< known value to check for memory stomping (e.g., (CD)*)
+ int32_t fID; ///< ID that can be used to track down leaks by clients.
#endif
BlockHeader* fHeader; ///< pointer back to the block header in which an alloc resides
};
#ifdef SK_DEBUG
int fAllocationCnt;
int fAllocBlockCnt;
+ SkTHashSet<int32_t> fAllocatedIDs;
#endif
protected: