Notify resource caches when pixelref genID goes stale

patch from issue 954443002 at patchset 40001 (http://crrev.com/954443002#ps40001)

BUG=skia:

Review URL: https://codereview.chromium.org/950363002
diff --git a/src/core/SkResourceCache.cpp b/src/core/SkResourceCache.cpp
index 4ed889a..9da90c4 100644
--- a/src/core/SkResourceCache.cpp
+++ b/src/core/SkResourceCache.cpp
@@ -6,12 +6,15 @@
  */
 
 #include "SkChecksum.h"
-#include "SkResourceCache.h"
+#include "SkMessageBus.h"
 #include "SkMipMap.h"
 #include "SkPixelRef.h"
+#include "SkResourceCache.h"
 
 #include <stddef.h>
 
+DECLARE_SKMESSAGEBUS_MESSAGE(SkResourceCache::PurgeSharedIDMessage)
+
 // This can be defined by the caller's build system
 //#define SK_USE_DISCARDABLE_SCALEDIMAGECACHE
 
@@ -23,18 +26,22 @@
     #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 kUnhashedLocal32s = 2; // fCache32 + fHash
+    static const int kSharedIDLocal32s = 2; // fSharedID_lo + fSharedID_hi
+    static const int kHashedLocal32s = kSharedIDLocal32s + (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_lo = (uint32_t)sharedID;
+    fSharedID_hi = (uint32_t)(sharedID >> 32);
     fNamespace = nameSpace;
     // skip unhashed fields when computing the murmur
     fHash = SkChecksum::Murmur3(this->as32() + kUnhashedLocal32s,
@@ -199,7 +206,9 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool SkResourceCache::find(const Key& key, VisitorProc visitor, void* context) {
+bool SkResourceCache::find(const Key& key, FindVisitor visitor, void* context) {
+    this->checkMessages();
+
     Rec* rec = fHash->find(key);
     if (rec) {
         if (visitor(*rec, context)) {
@@ -226,6 +235,8 @@
 static bool gDumpCacheTransactions;
 
 void SkResourceCache::add(Rec* rec) {
+    this->checkMessages();
+    
     SkASSERT(rec);
     // See if we already have this key (racy inserts, etc.)
     Rec* existing = fHash->find(rec->getKey());
@@ -294,6 +305,24 @@
     }
 }
 
+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) {
+//            SkDebugf("purgeSharedID id=%llx rec=%p\n", sharedID, rec);
+            this->remove(rec);
+        }
+        rec = prev;
+    }
+}
+
 size_t SkResourceCache::setTotalByteLimit(size_t newLimit) {
     size_t prevLimit = fTotalByteLimit;
     fTotalByteLimit = newLimit;
@@ -304,6 +333,8 @@
 }
 
 SkCachedData* SkResourceCache::newCachedData(size_t bytes) {
+    this->checkMessages();
+    
     if (fDiscardableFactory) {
         SkDiscardableMemory* dm = fDiscardableFactory(bytes);
         return dm ? SkNEW_ARGS(SkCachedData, (bytes, dm)) : NULL;
@@ -451,6 +482,14 @@
     return limit;
 }
 
+void SkResourceCache::checkMessages() {
+    SkTArray<PurgeSharedIDMessage> msgs;
+    fPurgeSharedIDInbox.poll(&msgs);
+    for (int i = 0; i < msgs.count(); ++i) {
+        this->purgeSharedID(msgs[i].fSharedID);
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkThread.h"
@@ -537,7 +576,7 @@
     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);
     return get_cache()->find(key, visitor, context);
 }
@@ -547,6 +586,12 @@
     get_cache()->add(rec);
 }
 
+void SkResourceCache::PostPurgeSharedID(uint64_t sharedID) {
+    if (sharedID) {
+        SkMessageBus<PurgeSharedIDMessage>::Post(PurgeSharedIDMessage(sharedID));
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////////
 
 #include "SkGraphics.h"