Index: src/core/SkChunkAlloc.cpp |
diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp |
index 62cdf1532f75b15738c296cf786d24b23ed1dfa0..dec50c99aa7952a81bf08cd3b4e934c2677d1fa2 100644 |
--- a/src/core/SkChunkAlloc.cpp |
+++ b/src/core/SkChunkAlloc.cpp |
@@ -23,6 +23,18 @@ struct SkChunkAlloc::Block { |
char* fFreePtr; |
// data[] follows |
+ size_t blockSize() { |
+ char* start = this->startOfData(); |
+ size_t bytes = fFreePtr - start; |
+ return fFreeSize + bytes; |
+ } |
+ |
+ void reset() { |
+ fNext = NULL; |
+ fFreeSize = this->blockSize(); |
+ fFreePtr = this->startOfData(); |
+ } |
+ |
char* startOfData() { |
return reinterpret_cast<char*>(this + 1); |
} |
@@ -69,6 +81,34 @@ void SkChunkAlloc::reset() { |
fBlockCount = 0; |
} |
+void SkChunkAlloc::rewind() { |
+ Block* largest = fBlock; |
+ |
+ if (largest) { |
+ Block* next; |
+ for (Block* cur = largest->fNext; cur; cur = next) { |
+ next = cur->fNext; |
+ if (cur->blockSize() > largest->blockSize()) { |
+ sk_free(largest); |
+ largest = cur; |
+ } else { |
+ sk_free(cur); |
+ } |
+ } |
+ |
+ largest->reset(); |
+ fTotalCapacity = largest->blockSize(); |
+ fBlockCount = 1; |
+ } else { |
+ fTotalCapacity = 0; |
+ fBlockCount = 0; |
+ } |
+ |
+ fBlock = largest; |
+ fChunkSize = fMinSize; // reset to our initial minSize |
+ fTotalUsed = 0; |
+} |
+ |
SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { |
size_t size = bytes; |
if (size < fChunkSize) { |
@@ -79,7 +119,6 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { |
ftype == kThrow_AllocFailType ? SK_MALLOC_THROW : 0); |
if (block) { |
- // block->fNext = fBlock; |
block->fFreeSize = size; |
block->fFreePtr = block->startOfData(); |
@@ -91,23 +130,38 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) { |
return block; |
} |
-void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { |
- fTotalUsed += bytes; |
- |
- bytes = SkAlign4(bytes); |
+SkChunkAlloc::Block* SkChunkAlloc::addBlockIfNecessary(size_t bytes, AllocFailType ftype) { |
+ SkASSERT(SkIsAlign4(bytes)); |
- Block* block = fBlock; |
- |
- if (block == NULL || bytes > block->fFreeSize) { |
- block = this->newBlock(bytes, ftype); |
- if (NULL == block) { |
+ if (!fBlock || bytes > fBlock->fFreeSize) { |
+ Block* block = this->newBlock(bytes, ftype); |
+ if (!block) { |
return NULL; |
} |
block->fNext = fBlock; |
fBlock = block; |
} |
- SkASSERT(block && bytes <= block->fFreeSize); |
+ SkASSERT(fBlock && bytes <= fBlock->fFreeSize); |
+ return fBlock; |
+} |
+ |
+void SkChunkAlloc::preAlloc(size_t bytes) { |
+ bytes = SkAlign4(bytes); |
+ |
+ this->addBlockIfNecessary(bytes, kReturnNil_AllocFailType); |
+} |
+ |
+void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) { |
+ fTotalUsed += bytes; |
+ |
+ bytes = SkAlign4(bytes); |
+ |
+ Block* block = this->addBlockIfNecessary(bytes, ftype); |
+ if (!block) { |
+ return NULL; |
+ } |
+ |
char* ptr = block->fFreePtr; |
block->fFreeSize -= bytes; |
@@ -123,6 +177,7 @@ size_t SkChunkAlloc::unalloc(void* ptr) { |
char* start = block->startOfData(); |
if (start <= cPtr && cPtr < block->fFreePtr) { |
bytes = block->fFreePtr - cPtr; |
+ fTotalUsed -= bytes; |
block->fFreeSize += bytes; |
block->fFreePtr = cPtr; |
} |