Move SkMessageBus::Get out of header, and retry crrev.com/106563002.

BUG=
R=bsalomon@google.com, kkinnunen@nvidia.com

Author: mtklein@google.com

Review URL: https://codereview.chromium.org/140053002

git-svn-id: http://skia.googlecode.com/svn/trunk@13104 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index 845094b..c912ae0 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -8,6 +8,7 @@
 #if SK_SUPPORT_GPU
 
 #include "GrContextFactory.h"
+#include "GrResourceCache.h"
 #include "SkGpuDevice.h"
 #include "Test.h"
 
@@ -57,6 +58,79 @@
     context->setTextureCacheLimits(oldMaxNum, oldMaxBytes);
 }
 
+class TestResource : public GrResource {
+public:
+    SK_DECLARE_INST_COUNT(TestResource);
+    explicit TestResource(GrGpu* gpu)
+        : INHERITED(gpu, false)
+        , fCache(NULL)
+        , fToDelete(NULL) {
+        ++fAlive;
+    }
+
+    ~TestResource() {
+        --fAlive;
+        if (NULL != fToDelete) {
+            // Breaks our little 2-element cycle below.
+            fToDelete->setDeleteWhenDestroyed(NULL, NULL);
+            fCache->deleteResource(fToDelete->getCacheEntry());
+        }
+        this->release();
+    }
+
+    size_t sizeInBytes() const SK_OVERRIDE { return 100; }
+
+    static int alive() { return fAlive; }
+
+    void setDeleteWhenDestroyed(GrResourceCache* cache, TestResource* resource) {
+        fCache = cache;
+        fToDelete = resource;
+    }
+
+private:
+    GrResourceCache* fCache;
+    TestResource* fToDelete;
+    static int fAlive;
+
+    typedef GrResource INHERITED;
+};
+int TestResource::fAlive = 0;
+
+static void test_purge_invalidated(skiatest::Reporter* reporter, GrContext* context) {
+    GrCacheID::Domain domain = GrCacheID::GenerateDomain();
+    GrCacheID::Key keyData;
+    keyData.fData64[0] = 5;
+    keyData.fData64[1] = 18;
+    GrResourceKey::ResourceType t = GrResourceKey::GenerateResourceType();
+    GrResourceKey key(GrCacheID(domain, keyData), t, 0);
+
+    GrResourceCache cache(5, 30000);
+
+    // Add two resources with the same key that delete each other from the cache when destroyed.
+    TestResource* a = new TestResource(context->getGpu());
+    TestResource* b = new TestResource(context->getGpu());
+    cache.addResource(key, a);
+    cache.addResource(key, b);
+    // Circle back.
+    a->setDeleteWhenDestroyed(&cache, b);
+    b->setDeleteWhenDestroyed(&cache, a);
+    a->unref();
+    b->unref();
+
+    // Add a third independent resource also with the same key.
+    GrResource* r = new TestResource(context->getGpu());
+    cache.addResource(key, r);
+    r->unref();
+
+    // Invalidate all three, all three should be purged and destroyed.
+    REPORTER_ASSERT(reporter, 3 == TestResource::alive());
+    const GrResourceInvalidatedMessage msg = { key };
+    SkMessageBus<GrResourceInvalidatedMessage>::Post(msg);
+    cache.purgeAsNeeded();
+    REPORTER_ASSERT(reporter, 0 == TestResource::alive());
+}
+
+////////////////////////////////////////////////////////////////////////////////
 DEF_GPUTEST(ResourceCache, reporter, factory) {
     for (int type = 0; type < GrContextFactory::kLastGLContextType; ++type) {
         GrContextFactory::GLContextType glType = static_cast<GrContextFactory::GLContextType>(type);
@@ -79,6 +153,7 @@
         SkCanvas canvas(device.get());
 
         test_cache(reporter, context, &canvas);
+        test_purge_invalidated(reporter, context);
     }
 }