Index: src/core/SkResourceCache.cpp |
diff --git a/src/core/SkResourceCache.cpp b/src/core/SkResourceCache.cpp |
index 4ed889a0aba3095900d934187f812f170217cca8..b8c0071f914ba4007f923d58ae59cad0ee81f470 100644 |
--- a/src/core/SkResourceCache.cpp |
+++ b/src/core/SkResourceCache.cpp |
@@ -23,18 +23,20 @@ |
#define SK_DEFAULT_IMAGE_CACHE_LIMIT (2 * 1024 * 1024) |
#endif |
-void SkResourceCache::Key::init(void* nameSpace, size_t length) { |
+void SkResourceCache::Key::init(void* nameSpace, uint64_t sharedID, size_t length) { |
SkASSERT(SkAlign4(length) == length); |
// fCount32 and fHash are not hashed |
static const int kUnhashedLocal32s = 2; |
- static const int kLocal32s = kUnhashedLocal32s + (sizeof(fNamespace) >> 2); |
+ static const int kHashedLocal32s = (sizeof(fSharedID) + sizeof(fNamespace)) >> 2; |
+ static const int kLocal32s = kUnhashedLocal32s + kHashedLocal32s; |
SK_COMPILE_ASSERT(sizeof(Key) == (kLocal32s << 2), unaccounted_key_locals); |
SK_COMPILE_ASSERT(sizeof(Key) == offsetof(Key, fNamespace) + sizeof(fNamespace), |
namespace_field_must_be_last); |
fCount32 = SkToS32(kLocal32s + (length >> 2)); |
+ fSharedID = sharedID; |
fNamespace = nameSpace; |
// skip unhashed fields when computing the murmur |
fHash = SkChecksum::Murmur3(this->as32() + kUnhashedLocal32s, |
@@ -199,7 +201,7 @@ SkResourceCache::~SkResourceCache() { |
//////////////////////////////////////////////////////////////////////////////// |
-bool SkResourceCache::find(const Key& key, VisitorProc visitor, void* context) { |
+bool SkResourceCache::find(const Key& key, FindVisitor visitor, void* context) { |
Rec* rec = fHash->find(key); |
if (rec) { |
if (visitor(*rec, context)) { |
@@ -294,6 +296,23 @@ void SkResourceCache::purgeAsNeeded(bool forcePurge) { |
} |
} |
+void SkResourceCache::purgeSharedID(uint64_t sharedID) { |
+ if (0 == sharedID) { |
+ return; |
+ } |
+ |
+ // go backwards, just like purgeAsNeeded, just to make the code similar. |
+ // could iterate either direction and still be correct. |
+ Rec* rec = fTail; |
+ while (rec) { |
+ Rec* prev = rec->fPrev; |
+ if (rec->getKey().getSharedID() == sharedID) { |
+ this->remove(rec); |
+ } |
+ rec = prev; |
+ } |
+} |
+ |
size_t SkResourceCache::setTotalByteLimit(size_t newLimit) { |
size_t prevLimit = fTotalByteLimit; |
fTotalByteLimit = newLimit; |
@@ -451,6 +470,16 @@ size_t SkResourceCache::getEffectiveSingleAllocationByteLimit() const { |
return limit; |
} |
+void SkResourceCache::checkMessages() { |
+ SkTDArray<uint64_t>* msgs = DetachPurgeMessages(); |
+ if (msgs) { |
+ for (int i = 0; i < msgs->count(); ++i) { |
+ this->purgeSharedID(msgs->getAt(i)); |
+ } |
+ delete msgs; |
+ } |
+} |
+ |
/////////////////////////////////////////////////////////////////////////////// |
#include "SkThread.h" |
@@ -509,6 +538,7 @@ SkBitmap::Allocator* SkResourceCache::GetAllocator() { |
SkCachedData* SkResourceCache::NewCachedData(size_t bytes) { |
SkAutoMutexAcquire am(gMutex); |
+ get_cache()->checkMessages(); |
return get_cache()->newCachedData(bytes); |
} |
@@ -532,23 +562,54 @@ size_t SkResourceCache::GetEffectiveSingleAllocationByteLimit() { |
return get_cache()->getEffectiveSingleAllocationByteLimit(); |
} |
+void SkResourceCache::PurgeSharedID(uint64_t sharedID) { |
+ if (sharedID) { |
+ SkAutoMutexAcquire am(gMutex); |
+ return get_cache()->purgeSharedID(sharedID); |
+ } |
+} |
+ |
void SkResourceCache::PurgeAll() { |
SkAutoMutexAcquire am(gMutex); |
return get_cache()->purgeAll(); |
} |
-bool SkResourceCache::Find(const Key& key, VisitorProc visitor, void* context) { |
+bool SkResourceCache::Find(const Key& key, FindVisitor visitor, void* context) { |
SkAutoMutexAcquire am(gMutex); |
+ get_cache()->checkMessages(); |
return get_cache()->find(key, visitor, context); |
} |
void SkResourceCache::Add(Rec* rec) { |
SkAutoMutexAcquire am(gMutex); |
+ get_cache()->checkMessages(); |
get_cache()->add(rec); |
} |
/////////////////////////////////////////////////////////////////////////////// |
+static SkTDArray<uint64_t>* gPurgePayloads; |
+static SkMutex gPuragePayloadMutex; |
+ |
+void SkResourceCache::PostPurgeSharedID(uint64_t sharedID) { |
+ if (sharedID) { |
+ SkAutoMutexAcquire am(gPuragePayloadMutex); |
+ if (NULL == gPurgePayloads) { |
+ gPurgePayloads = new SkTDArray<uint64_t>; |
+ } |
+ *gPurgePayloads->append() = sharedID; |
+ } |
+} |
+ |
+SkTDArray<uint64_t>* SkResourceCache::DetachPurgeMessages() { |
+ SkAutoMutexAcquire am(gPuragePayloadMutex); |
+ SkTDArray<uint64_t>* payloads = gPurgePayloads; |
+ gPurgePayloads = NULL; |
+ return payloads; |
+} |
+ |
+/////////////////////////////////////////////////////////////////////////////// |
+ |
#include "SkGraphics.h" |
size_t SkGraphics::GetResourceCacheTotalBytesUsed() { |