diff options
author | reed <reed@google.com> | 2014-09-15 10:15:18 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-15 10:15:18 -0700 |
commit | 595aa05efcb504e85358b8d328ac4a9fa1c46e2e (patch) | |
tree | 573f666cd9ed981bca2d33ed384051e95ff3412d /src | |
parent | 81940de68893e6a643301f9930db630764729ea8 (diff) |
Revert of Change SkResourceCache to take a Visitor inside its find(). (patchset #2 id:20001 of https://codereview.chromium.org/567393002/)
Reason for revert:
crashes on android bots, haven't diagnosed yet
Original issue's description:
> Change SkResourceCache to take a Visitor inside its find().
>
> This simplifies the API/contract, in that there are not any exposed
> lock/unlock scopes.
>
>
> patch from issue 572573002
>
> BUG=skia:
>
> Committed: https://skia.googlesource.com/skia/+/dee6a8e67db39fcbde2b3bb09be1d088ebb9db8a
R=mtklein@google.com, danakj@chromium.org
TBR=danakj@chromium.org, mtklein@google.com
NOTREECHECKS=true
NOTRY=true
BUG=skia:
Author: reed@google.com
Review URL: https://codereview.chromium.org/569303002
Diffstat (limited to 'src')
-rw-r--r-- | src/core/SkBitmapCache.cpp | 43 | ||||
-rw-r--r-- | src/core/SkResourceCache.cpp | 120 | ||||
-rw-r--r-- | src/core/SkResourceCache.h | 49 |
3 files changed, 144 insertions, 68 deletions
diff --git a/src/core/SkBitmapCache.cpp b/src/core/SkBitmapCache.cpp index 84f10363f0..6d4f4b4cc7 100644 --- a/src/core/SkBitmapCache.cpp +++ b/src/core/SkBitmapCache.cpp @@ -59,16 +59,25 @@ struct BitmapRec : public SkResourceCache::Rec { virtual const Key& getKey() const SK_OVERRIDE { return fKey; } virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fBitmap.getSize(); } +}; - static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextBitmap) { - const BitmapRec& rec = static_cast<const BitmapRec&>(baseRec); - SkBitmap* result = (SkBitmap*)contextBitmap; +static bool find_and_return(const BitmapKey& key, SkBitmap* result) { + const BitmapRec* rec = (BitmapRec*)SkResourceCache::FindAndLock(key); + if (rec) { + *result = rec->fBitmap; + SkResourceCache::Unlock(rec); - *result = rec.fBitmap; result->lockPixels(); - return SkToBool(result->getPixels()); + if (result->getPixels()) { + return true; + } + + SkResourceCache::Remove(rec); + result->reset(); + // fall-through to false } -}; + return false; +} bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY, SkBitmap* result) { @@ -77,7 +86,7 @@ bool SkBitmapCache::Find(const SkBitmap& src, SkScalar invScaleX, SkScalar invSc return false; } BitmapKey key(src.getGenerationID(), invScaleX, invScaleY, get_bounds_from_bitmap(src)); - return SkResourceCache::Find(key, BitmapRec::Visitor, result); + return find_and_return(key, result); } void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invScaleY, @@ -93,7 +102,7 @@ void SkBitmapCache::Add(const SkBitmap& src, SkScalar invScaleX, SkScalar invSca bool SkBitmapCache::Find(uint32_t genID, const SkIRect& subset, SkBitmap* result) { BitmapKey key(genID, SK_Scalar1, SK_Scalar1, subset); - return SkResourceCache::Find(key, BitmapRec::Visitor, result); + return find_and_return(key, result); } bool SkBitmapCache::Add(uint32_t genID, const SkIRect& subset, const SkBitmap& result) { @@ -129,22 +138,16 @@ struct MipMapRec : public SkResourceCache::Rec { virtual const Key& getKey() const SK_OVERRIDE { return fKey; } virtual size_t bytesUsed() const SK_OVERRIDE { return sizeof(fKey) + fMipMap->getSize(); } - - static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextMip) { - const MipMapRec& rec = static_cast<const MipMapRec&>(baseRec); - const SkMipMap** result = (const SkMipMap**)contextMip; - - *result = SkRef(rec.fMipMap); - // mipmaps don't use the custom allocator yet, so we don't need to check pixels - return true; - } }; + const SkMipMap* SkMipMapCache::FindAndRef(const SkBitmap& src) { BitmapKey key(src.getGenerationID(), 0, 0, get_bounds_from_bitmap(src)); - const SkMipMap* result; - if (!SkResourceCache::Find(key, MipMapRec::Visitor, &result)) { - result = NULL; + const MipMapRec* rec = (MipMapRec*)SkResourceCache::FindAndLock(key); + const SkMipMap* result = NULL; + if (rec) { + result = SkRef(rec->fMipMap); + SkResourceCache::Unlock(rec); } return result; } diff --git a/src/core/SkResourceCache.cpp b/src/core/SkResourceCache.cpp index 85b5b907b1..68248f512b 100644 --- a/src/core/SkResourceCache.cpp +++ b/src/core/SkResourceCache.cpp @@ -187,34 +187,80 @@ SkResourceCache::~SkResourceCache() { //////////////////////////////////////////////////////////////////////////////// -bool SkResourceCache::find(const Key& key, VisitorProc visitor, void* context) { +const SkResourceCache::Rec* SkResourceCache::findAndLock(const Key& key) { Rec* rec = fHash->find(key); if (rec) { - if (visitor(*rec, context)) { - this->moveToHead(rec); // for our LRU - return true; - } else { - this->remove(rec); // stale - return false; - } + this->moveToHead(rec); // for our LRU + rec->fLockCount += 1; } - return false; + return rec; +} + +const SkResourceCache::Rec* SkResourceCache::addAndLock(Rec* rec) { + SkASSERT(rec); + // See if we already have this key (racy inserts, etc.) + const Rec* existing = this->findAndLock(rec->getKey()); + if (existing) { + SkDELETE(rec); + return existing; + } + + this->addToHead(rec); + SkASSERT(1 == rec->fLockCount); + fHash->add(rec); + // We may (now) be overbudget, so see if we need to purge something. + this->purgeAsNeeded(); + return rec; } void SkResourceCache::add(Rec* rec) { SkASSERT(rec); // See if we already have this key (racy inserts, etc.) - Rec* existing = fHash->find(rec->getKey()); + const Rec* existing = this->findAndLock(rec->getKey()); if (existing) { SkDELETE(rec); + this->unlock(existing); return; } this->addToHead(rec); + SkASSERT(1 == rec->fLockCount); fHash->add(rec); + this->unlock(rec); +} + +void SkResourceCache::unlock(SkResourceCache::ID id) { + SkASSERT(id); + +#ifdef SK_DEBUG + { + bool found = false; + Rec* rec = fHead; + while (rec != NULL) { + if (rec == id) { + found = true; + break; + } + rec = rec->fNext; + } + SkASSERT(found); + } +#endif + const Rec* rec = id; + SkASSERT(rec->fLockCount > 0); + // We're under our lock, and we're the only possible mutator, so unconsting is fine. + const_cast<Rec*>(rec)->fLockCount -= 1; + + // we may have been over-budget, but now have released something, so check + // if we should purge. + if (0 == rec->fLockCount) { + this->purgeAsNeeded(); + } } void SkResourceCache::remove(Rec* rec) { + SkASSERT(0 == rec->fLockCount); + size_t used = rec->bytesUsed(); SkASSERT(used <= fTotalBytesUsed); @@ -246,7 +292,9 @@ void SkResourceCache::purgeAsNeeded(bool forcePurge) { } Rec* prev = rec->fPrev; - this->remove(rec); + if (0 == rec->fLockCount) { + this->remove(rec); + } rec = prev; } } @@ -369,8 +417,16 @@ void SkResourceCache::validate() const { void SkResourceCache::dump() const { this->validate(); - SkDebugf("SkResourceCache: count=%d bytes=%d %s\n", - fCount, fTotalBytesUsed, fDiscardableFactory ? "discardable" : "malloc"); + const Rec* rec = fHead; + int locked = 0; + while (rec) { + locked += rec->fLockCount > 0; + rec = rec->fNext; + } + + SkDebugf("SkResourceCache: count=%d bytes=%d locked=%d %s\n", + fCount, fTotalBytesUsed, locked, + fDiscardableFactory ? "discardable" : "malloc"); } size_t SkResourceCache::setSingleAllocationByteLimit(size_t newLimit) { @@ -414,6 +470,35 @@ static SkResourceCache* get_cache() { return gResourceCache; } +void SkResourceCache::Unlock(SkResourceCache::ID id) { + SkAutoMutexAcquire am(gMutex); + get_cache()->unlock(id); + +// get_cache()->dump(); +} + +void SkResourceCache::Remove(SkResourceCache::ID id) { + SkAutoMutexAcquire am(gMutex); + SkASSERT(id); + +#ifdef SK_DEBUG + { + bool found = false; + Rec* rec = get_cache()->fHead; + while (rec != NULL) { + if (rec == id) { + found = true; + break; + } + rec = rec->fNext; + } + SkASSERT(found); + } +#endif + const Rec* rec = id; + get_cache()->remove(const_cast<Rec*>(rec)); +} + size_t SkResourceCache::GetTotalBytesUsed() { SkAutoMutexAcquire am(gMutex); return get_cache()->getTotalBytesUsed(); @@ -454,9 +539,14 @@ void SkResourceCache::PurgeAll() { return get_cache()->purgeAll(); } -bool SkResourceCache::Find(const Key& key, VisitorProc visitor, void* context) { +const SkResourceCache::Rec* SkResourceCache::FindAndLock(const Key& key) { + SkAutoMutexAcquire am(gMutex); + return get_cache()->findAndLock(key); +} + +const SkResourceCache::Rec* SkResourceCache::AddAndLock(Rec* rec) { SkAutoMutexAcquire am(gMutex); - return get_cache()->find(key, visitor, context); + return get_cache()->addAndLock(rec); } void SkResourceCache::Add(Rec* rec) { diff --git a/src/core/SkResourceCache.h b/src/core/SkResourceCache.h index d4e1dfa376..dacd62cedb 100644 --- a/src/core/SkResourceCache.h +++ b/src/core/SkResourceCache.h @@ -60,7 +60,7 @@ public: struct Rec { typedef SkResourceCache::Key Key; - Rec() {} + Rec() : fLockCount(1) {} virtual ~Rec() {} uint32_t getHash() const { return this->getKey().hash(); } @@ -75,6 +75,7 @@ public: private: Rec* fNext; Rec* fPrev; + int32_t fLockCount; friend class SkResourceCache; }; @@ -82,18 +83,6 @@ public: typedef const Rec* ID; /** - * Callback function for find(). If called, the cache will have found a match for the - * specified Key, and will pass in the corresponding Rec, along with a caller-specified - * context. The function can read the data in Rec, and copy whatever it likes into context - * (casting context to whatever it really is). - * - * The return value determines what the cache will do with the Rec. If the function returns - * true, then the Rec is considered "valid". If false is returned, the Rec will be considered - * "stale" and will be purged from the cache. - */ - typedef bool (*VisitorProc)(const Rec&, void* context); - - /** * Returns a locked/pinned SkDiscardableMemory instance for the specified * number of bytes, or NULL on failure. */ @@ -104,17 +93,11 @@ public: * instance of this cache. */ - /** - * Returns true if the visitor was called on a matching Key, and the visitor returned true. - * - * Find() will search the cache for the specified Key. If no match is found, return false and - * do not call the VisitorProc. If a match is found, return whatever the visitor returns. - * Its return value is interpreted to mean: - * true : Rec is valid - * false : Rec is "stale" -- the cache will purge it. - */ - static bool Find(const Key& key, VisitorProc, void* context); + static const Rec* FindAndLock(const Key& key); + static const Rec* AddAndLock(Rec*); static void Add(Rec*); + static void Unlock(ID); + static void Remove(ID); static size_t GetTotalBytesUsed(); static size_t GetTotalByteLimit(); @@ -156,17 +139,18 @@ public: explicit SkResourceCache(size_t byteLimit); ~SkResourceCache(); + const Rec* findAndLock(const Key& key); + const Rec* addAndLock(Rec*); + void add(Rec*); + void remove(Rec*); + /** - * Returns true if the visitor was called on a matching Key, and the visitor returned true. - * - * find() will search the cache for the specified Key. If no match is found, return false and - * do not call the VisitorProc. If a match is found, return whatever the visitor returns. - * Its return value is interpreted to mean: - * true : Rec is valid - * false : Rec is "stale" -- the cache will purge it. + * Given a non-null ID ptr returned by either findAndLock or addAndLock, + * this releases the associated resources to be available to be purged + * if needed. After this, the cached bitmap should no longer be + * referenced by the caller. */ - bool find(const Key&, VisitorProc, void* context); - void add(Rec*); + void unlock(ID); size_t getTotalBytesUsed() const { return fTotalBytesUsed; } size_t getTotalByteLimit() const { return fTotalByteLimit; } @@ -218,7 +202,6 @@ private: void moveToHead(Rec*); void addToHead(Rec*); void detach(Rec*); - void remove(Rec*); void init(); // called by constructors |