SkDiscardableMemoryPool to abstract class
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 4 Apr 2014 16:43:38 +0000 (16:43 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Fri, 4 Apr 2014 16:43:38 +0000 (16:43 +0000)
Motivation - we want to keep our public headers small.

R=scroggo@google.com, reed@google.com

Author: halcanary@google.com

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

git-svn-id: http://skia.googlecode.com/svn/trunk@14063 2bbb7eff-a529-9590-31e7-b0007b416f81

gm/factory.cpp
src/lazy/SkDiscardableMemoryPool.cpp
src/lazy/SkDiscardableMemoryPool.h
tests/CachedDecodingPixelRefTest.cpp
tests/DiscardableMemoryPoolTest.cpp
tests/DrawBitmapRectTest.cpp
tests/ImageCacheTest.cpp
tools/bench_pictures_main.cpp

index efd817d..29cf7ea 100644 (file)
@@ -35,7 +35,7 @@ protected:
             // Create a cache which will boot the pixels out anytime the
             // bitmap is unlocked.
             SkAutoTUnref<SkDiscardableMemoryPool> pool(
-                SkNEW_ARGS(SkDiscardableMemoryPool, (1)));
+                SkDiscardableMemoryPool::Create(1));
             SkAssertResult(SkInstallDiscardablePixelRef(
                 SkDecodingImageGenerator::Create(
                     data, SkDecodingImageGenerator::Options()),
index 4709709..9612169 100644 (file)
@@ -5,37 +5,95 @@
  * found in the LICENSE file.
  */
 
+#include "SkDiscardableMemory.h"
 #include "SkDiscardableMemoryPool.h"
 #include "SkOnce.h"
+#include "SkTInternalLList.h"
+#include "SkThread.h"
 
 // Note:
 // A PoolDiscardableMemory is memory that is counted in a pool.
 // A DiscardableMemoryPool is a pool of PoolDiscardableMemorys.
 
+namespace {
+
+class PoolDiscardableMemory;
+
 /**
- *  A SkPoolDiscardableMemory is a SkDiscardableMemory that relies on
- *  a SkDiscardableMemoryPool object to manage the memory.
+ *  This non-global pool can be used for unit tests to verify that the
+ *  pool works.
  */
-class SkPoolDiscardableMemory : public SkDiscardableMemory {
+class DiscardableMemoryPool : public SkDiscardableMemoryPool {
 public:
-    SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
+    /**
+     *  Without mutex, will be not be thread safe.
+     */
+    DiscardableMemoryPool(size_t budget, SkBaseMutex* mutex = NULL);
+    virtual ~DiscardableMemoryPool();
+
+    virtual SkDiscardableMemory* create(size_t bytes) SK_OVERRIDE;
+
+    virtual size_t getRAMUsed() SK_OVERRIDE;
+    virtual void setRAMBudget(size_t budget) SK_OVERRIDE;
+    virtual size_t getRAMBudget() SK_OVERRIDE { return fBudget; }
+
+    /** purges all unlocked DMs */
+    virtual void dumpPool() SK_OVERRIDE;
+
+    #if SK_LAZY_CACHE_STATS  // Defined in SkDiscardableMemoryPool.h
+    virtual int getCacheHits() SK_OVERRIDE { return fCacheHits; }
+    virtual int getCacheMisses() SK_OVERRIDE { return fCacheMisses; }
+    virtual void resetCacheHitsAndMisses() SK_OVERRIDE {
+        fCacheHits = fCacheMisses = 0;
+    }
+    int          fCacheHits;
+    int          fCacheMisses;
+    #endif  // SK_LAZY_CACHE_STATS
+
+private:
+    SkBaseMutex* fMutex;
+    size_t       fBudget;
+    size_t       fUsed;
+    SkTInternalLList<PoolDiscardableMemory> fList;
+
+    /** Function called to free memory if needed */
+    void dumpDownTo(size_t budget);
+    /** called by DiscardableMemoryPool upon destruction */
+    void free(PoolDiscardableMemory* dm);
+    /** called by DiscardableMemoryPool::lock() */
+    bool lock(PoolDiscardableMemory* dm);
+    /** called by DiscardableMemoryPool::unlock() */
+    void unlock(PoolDiscardableMemory* dm);
+
+    friend class PoolDiscardableMemory;
+
+    typedef SkDiscardableMemory::Factory INHERITED;
+};
+
+/**
+ *  A PoolDiscardableMemory is a SkDiscardableMemory that relies on
+ *  a DiscardableMemoryPool object to manage the memory.
+ */
+class PoolDiscardableMemory : public SkDiscardableMemory {
+public:
+    PoolDiscardableMemory(DiscardableMemoryPool* pool,
                             void* pointer, size_t bytes);
-    virtual ~SkPoolDiscardableMemory();
+    virtual ~PoolDiscardableMemory();
     virtual bool lock() SK_OVERRIDE;
     virtual void* data() SK_OVERRIDE;
     virtual void unlock() SK_OVERRIDE;
-    friend class SkDiscardableMemoryPool;
+    friend class DiscardableMemoryPool;
 private:
-    SK_DECLARE_INTERNAL_LLIST_INTERFACE(SkPoolDiscardableMemory);
-    SkDiscardableMemoryPool* const fPool;
-    bool                           fLocked;
-    void*                          fPointer;
-    const size_t                   fBytes;
+    SK_DECLARE_INTERNAL_LLIST_INTERFACE(PoolDiscardableMemory);
+    DiscardableMemoryPool* const fPool;
+    bool                         fLocked;
+    void*                        fPointer;
+    const size_t                 fBytes;
 };
 
-SkPoolDiscardableMemory::SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
-                                                 void* pointer,
-                                                 size_t bytes)
+PoolDiscardableMemory::PoolDiscardableMemory(DiscardableMemoryPool* pool,
+                                             void* pointer,
+                                             size_t bytes)
     : fPool(pool)
     , fLocked(true)
     , fPointer(pointer)
@@ -46,59 +104,59 @@ SkPoolDiscardableMemory::SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
     fPool->ref();
 }
 
-SkPoolDiscardableMemory::~SkPoolDiscardableMemory() {
+PoolDiscardableMemory::~PoolDiscardableMemory() {
     SkASSERT(!fLocked); // contract for SkDiscardableMemory
     fPool->free(this);
     fPool->unref();
 }
 
-bool SkPoolDiscardableMemory::lock() {
+bool PoolDiscardableMemory::lock() {
     SkASSERT(!fLocked); // contract for SkDiscardableMemory
     return fPool->lock(this);
 }
 
-void* SkPoolDiscardableMemory::data() {
+void* PoolDiscardableMemory::data() {
     SkASSERT(fLocked); // contract for SkDiscardableMemory
     return fPointer;
 }
 
-void SkPoolDiscardableMemory::unlock() {
+void PoolDiscardableMemory::unlock() {
     SkASSERT(fLocked); // contract for SkDiscardableMemory
     fPool->unlock(this);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 
-SkDiscardableMemoryPool::SkDiscardableMemoryPool(size_t budget,
-                                                 SkBaseMutex* mutex)
+DiscardableMemoryPool::DiscardableMemoryPool(size_t budget,
+                                             SkBaseMutex* mutex)
     : fMutex(mutex)
     , fBudget(budget)
     , fUsed(0) {
-    #if LAZY_CACHE_STATS
+    #if SK_LAZY_CACHE_STATS
     fCacheHits = 0;
     fCacheMisses = 0;
-    #endif  // LAZY_CACHE_STATS
+    #endif  // SK_LAZY_CACHE_STATS
 }
-SkDiscardableMemoryPool::~SkDiscardableMemoryPool() {
-    // SkPoolDiscardableMemory objects that belong to this pool are
+DiscardableMemoryPool::~DiscardableMemoryPool() {
+    // PoolDiscardableMemory objects that belong to this pool are
     // always deleted before deleting this pool since each one has a
     // ref to the pool.
     SkASSERT(fList.isEmpty());
 }
 
-void SkDiscardableMemoryPool::dumpDownTo(size_t budget) {
+void DiscardableMemoryPool::dumpDownTo(size_t budget) {
     // assert((NULL = fMutex) || fMutex->isLocked());
     // TODO(halcanary) implement bool fMutex::isLocked().
     // WARNING: only call this function after aquiring lock.
     if (fUsed <= budget) {
         return;
     }
-    typedef SkTInternalLList<SkPoolDiscardableMemory>::Iter Iter;
+    typedef SkTInternalLList<PoolDiscardableMemory>::Iter Iter;
     Iter iter;
-    SkPoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
+    PoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
     while ((fUsed > budget) && (NULL != cur)) {
         if (!cur->fLocked) {
-            SkPoolDiscardableMemory* dm = cur;
+            PoolDiscardableMemory* dm = cur;
             SkASSERT(dm->fPointer != NULL);
             sk_free(dm->fPointer);
             dm->fPointer = NULL;
@@ -114,12 +172,12 @@ void SkDiscardableMemoryPool::dumpDownTo(size_t budget) {
     }
 }
 
-SkDiscardableMemory* SkDiscardableMemoryPool::create(size_t bytes) {
+SkDiscardableMemory* DiscardableMemoryPool::create(size_t bytes) {
     void* addr = sk_malloc_flags(bytes, 0);
     if (NULL == addr) {
         return NULL;
     }
-    SkPoolDiscardableMemory* dm = SkNEW_ARGS(SkPoolDiscardableMemory,
+    PoolDiscardableMemory* dm = SkNEW_ARGS(PoolDiscardableMemory,
                                              (this, addr, bytes));
     SkAutoMutexAcquire autoMutexAcquire(fMutex);
     fList.addToHead(dm);
@@ -128,7 +186,7 @@ SkDiscardableMemory* SkDiscardableMemoryPool::create(size_t bytes) {
     return dm;
 }
 
-void SkDiscardableMemoryPool::free(SkPoolDiscardableMemory* dm) {
+void DiscardableMemoryPool::free(PoolDiscardableMemory* dm) {
     // This is called by dm's destructor.
     if (dm->fPointer != NULL) {
         SkAutoMutexAcquire autoMutexAcquire(fMutex);
@@ -142,64 +200,73 @@ void SkDiscardableMemoryPool::free(SkPoolDiscardableMemory* dm) {
     }
 }
 
-bool SkDiscardableMemoryPool::lock(SkPoolDiscardableMemory* dm) {
+bool DiscardableMemoryPool::lock(PoolDiscardableMemory* dm) {
     SkASSERT(dm != NULL);
     if (NULL == dm->fPointer) {
-        #if LAZY_CACHE_STATS
+        #if SK_LAZY_CACHE_STATS
         SkAutoMutexAcquire autoMutexAcquire(fMutex);
         ++fCacheMisses;
-        #endif  // LAZY_CACHE_STATS
+        #endif  // SK_LAZY_CACHE_STATS
         return false;
     }
     SkAutoMutexAcquire autoMutexAcquire(fMutex);
     if (NULL == dm->fPointer) {
         // May have been purged while waiting for lock.
-        #if LAZY_CACHE_STATS
+        #if SK_LAZY_CACHE_STATS
         ++fCacheMisses;
-        #endif  // LAZY_CACHE_STATS
+        #endif  // SK_LAZY_CACHE_STATS
         return false;
     }
     dm->fLocked = true;
     fList.remove(dm);
     fList.addToHead(dm);
-    #if LAZY_CACHE_STATS
+    #if SK_LAZY_CACHE_STATS
     ++fCacheHits;
-    #endif  // LAZY_CACHE_STATS
+    #endif  // SK_LAZY_CACHE_STATS
     return true;
 }
 
-void SkDiscardableMemoryPool::unlock(SkPoolDiscardableMemory* dm) {
+void DiscardableMemoryPool::unlock(PoolDiscardableMemory* dm) {
     SkASSERT(dm != NULL);
     SkAutoMutexAcquire autoMutexAcquire(fMutex);
     dm->fLocked = false;
     this->dumpDownTo(fBudget);
 }
 
-size_t SkDiscardableMemoryPool::getRAMUsed() {
+size_t DiscardableMemoryPool::getRAMUsed() {
     return fUsed;
 }
-void SkDiscardableMemoryPool::setRAMBudget(size_t budget) {
+void DiscardableMemoryPool::setRAMBudget(size_t budget) {
     SkAutoMutexAcquire autoMutexAcquire(fMutex);
     fBudget = budget;
     this->dumpDownTo(fBudget);
 }
-void SkDiscardableMemoryPool::dumpPool() {
+void DiscardableMemoryPool::dumpPool() {
     SkAutoMutexAcquire autoMutexAcquire(fMutex);
     this->dumpDownTo(0);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 SK_DECLARE_STATIC_MUTEX(gMutex);
-static void create_pool(SkDiscardableMemoryPool** pool) {
-    SkASSERT(NULL == *pool);
-    *pool = SkNEW_ARGS(SkDiscardableMemoryPool,
-                       (SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE,
-                        &gMutex));
+SkDiscardableMemoryPool* gPool = NULL;
+void create_global_pool(int) {
+    SkASSERT(NULL == gPool);
+    gPool = SkDiscardableMemoryPool::Create(
+            SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE, &gMutex);
+}
+void cleanup_global_pool() {
+    gPool->unref();
 }
+}  // namespace
+
+SkDiscardableMemoryPool* SkDiscardableMemoryPool::Create(
+        size_t size, SkBaseMutex* mutex) {
+    return SkNEW_ARGS(DiscardableMemoryPool, (size, mutex));
+}
+
 SkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() {
-    static SkDiscardableMemoryPool* gPool(NULL);
     SK_DECLARE_STATIC_ONCE(create_pool_once);
-    SkOnce(&create_pool_once, create_pool, &gPool);
+    SkOnce(&create_pool_once, create_global_pool, 0, &cleanup_global_pool);
     SkASSERT(NULL != gPool);
     return gPool;
 }
index 61bad70..d141507 100644 (file)
@@ -9,60 +9,50 @@
 #define SkDiscardableMemoryPool_DEFINED
 
 #include "SkDiscardableMemory.h"
-#include "SkTInternalLList.h"
-#include "SkThread.h"
 
-class SkPoolDiscardableMemory;
-
-#ifdef SK_DEBUG
-    #define LAZY_CACHE_STATS 1
-#elif !defined(LAZY_CACHE_STATS)
-    #define LAZY_CACHE_STATS 0
+#ifndef SK_LAZY_CACHE_STATS
+    #ifdef SK_DEBUG
+        #define SK_LAZY_CACHE_STATS 1
+    #else
+        #define SK_LAZY_CACHE_STATS 0
+    #endif
 #endif
 
 /**
- *  This non-global pool can be used for unit tests to verify that the
- *  pool works.
+ *  An implementation of Discardable Memory that manages a fixed-size
+ *  budget of memory.  When the allocated memory exceeds this size,
+ *  unlocked blocks of memory are purged.  If all memory is locked, it
+ *  can exceed the memory-use budget.
  */
 class SkDiscardableMemoryPool : public SkDiscardableMemory::Factory {
 public:
-    /**
-     *  Without mutex, will be not be thread safe.
-     */
-    SkDiscardableMemoryPool(size_t budget, SkBaseMutex* mutex = NULL);
-    virtual ~SkDiscardableMemoryPool();
+    virtual ~SkDiscardableMemoryPool() { }
 
-    virtual SkDiscardableMemory* create(size_t bytes) SK_OVERRIDE;
-
-    size_t getRAMUsed();
-    void setRAMBudget(size_t budget);
+    virtual size_t getRAMUsed() = 0;
+    virtual void setRAMBudget(size_t budget) = 0;
+    virtual size_t getRAMBudget() = 0;
 
     /** purges all unlocked DMs */
-    void dumpPool();
-
-    #if LAZY_CACHE_STATS
-    int          fCacheHits;
-    int          fCacheMisses;
-    #endif  // LAZY_CACHE_STATS
-
-private:
-    SkBaseMutex* fMutex;
-    size_t       fBudget;
-    size_t       fUsed;
-    SkTInternalLList<SkPoolDiscardableMemory> fList;
+    virtual void dumpPool() = 0;
 
-    /** Function called to free memory if needed */
-    void dumpDownTo(size_t budget);
-    /** called by SkDiscardableMemoryPool upon destruction */
-    void free(SkPoolDiscardableMemory* dm);
-    /** called by SkDiscardableMemoryPool::lock() */
-    bool lock(SkPoolDiscardableMemory* dm);
-    /** called by SkDiscardableMemoryPool::unlock() */
-    void unlock(SkPoolDiscardableMemory* dm);
-
-    friend class SkPoolDiscardableMemory;
+    #if SK_LAZY_CACHE_STATS
+    /**
+     * These two values are a count of the number of successful and
+     * failed calls to SkDiscardableMemory::lock() for all DMs managed
+     * by this pool.
+     */
+    virtual int getCacheHits() = 0;
+    virtual int getCacheMisses() = 0;
+    virtual void resetCacheHitsAndMisses() = 0;
+    #endif
 
-    typedef SkDiscardableMemory::Factory INHERITED;
+    /**
+     *  This non-global pool can be used for unit tests to verify that
+     *  the pool works.
+     *  Without mutex, will be not be thread safe.
+     */
+    static SkDiscardableMemoryPool* Create(
+            size_t size, SkBaseMutex* mutex = NULL);
 };
 
 /**
index f984123..b2ecb0f 100644 (file)
@@ -303,7 +303,7 @@ DEF_TEST(DiscardableAndCachingPixelRef, reporter) {
                    reporter, kSkDiscardable_PixelRefType, NULL);
 
     SkAutoTUnref<SkDiscardableMemoryPool> pool(
-        SkNEW_ARGS(SkDiscardableMemoryPool, (1, NULL)));
+        SkDiscardableMemoryPool::Create(1, NULL));
     REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
     check_pixelref(TestImageGenerator::kFailGetPixels_TestType,
                    reporter, kSkDiscardable_PixelRefType, pool);
index dc927bd..e0145bc 100644 (file)
@@ -10,7 +10,7 @@
 
 DEF_TEST(DiscardableMemoryPool, reporter) {
     SkAutoTUnref<SkDiscardableMemoryPool> pool(
-        SkNEW_ARGS(SkDiscardableMemoryPool, (1, NULL)));
+        SkDiscardableMemoryPool::Create(1, NULL));
     pool->setRAMBudget(3);
     REPORTER_ASSERT(reporter, 0 == pool->getRAMUsed());
 
index f51bf53..f778480 100644 (file)
@@ -43,8 +43,8 @@ public:
 //
 static void test_faulty_pixelref(skiatest::Reporter* reporter) {
     // need a cache, but don't expect to use it, so the budget is not critical
-    SkAutoTUnref<SkDiscardableMemoryPool> pool(SkNEW_ARGS(SkDiscardableMemoryPool,
-                                                          (10 * 1000, NULL)));
+    SkAutoTUnref<SkDiscardableMemoryPool> pool(
+        SkDiscardableMemoryPool::Create(10 * 1000, NULL));
     SkBitmap bm;
     bool installSuccess = SkInstallDiscardablePixelRef(SkNEW(FailureImageGenerator), &bm, pool);
     REPORTER_ASSERT(reporter, installSuccess);
index 43a5e70..92d0b51 100644 (file)
@@ -81,6 +81,7 @@ static void test_cache(skiatest::Reporter* reporter, SkScaledImageCache& cache,
 
 static SkDiscardableMemoryPool* gPool;
 static SkDiscardableMemory* pool_factory(size_t bytes) {
+    SkASSERT(gPool);
     return gPool->create(bytes);
 }
 
@@ -92,8 +93,9 @@ DEF_TEST(ImageCache, reporter) {
         test_cache(reporter, cache, true);
     }
     {
-        SkDiscardableMemoryPool pool(defLimit);
-        gPool = &pool;
+        SkAutoTUnref<SkDiscardableMemoryPool> pool(
+                SkDiscardableMemoryPool::Create(defLimit, NULL));
+        gPool = pool.get();
         SkScaledImageCache cache(pool_factory);
         test_cache(reporter, cache, true);
     }
index 5829e18..4952571 100644 (file)
@@ -46,8 +46,8 @@ DEFINE_bool(purgeDecodedTex, false, "Purge decoded and GPU-uploaded textures "
 DEFINE_string(timers, "c", "[wcgWC]*: Display wall, cpu, gpu, truncated wall or truncated cpu time"
               " for each picture.");
 DEFINE_bool(trackDeferredCaching, false, "Only meaningful with --deferImageDecoding and "
-            "LAZY_CACHE_STATS set to true. Report percentage of cache hits when using deferred "
-            "image decoding.");
+            "SK_LAZY_CACHE_STATS set to true. Report percentage of cache hits when using "
+            "deferred image decoding.");
 
 static char const * const gFilterTypes[] = {
     "paint",
@@ -142,7 +142,7 @@ static SkString filterFlagsUsage() {
     return result;
 }
 
-#if LAZY_CACHE_STATS
+#if SK_LAZY_CACHE_STATS
 static int32_t gTotalCacheHits;
 static int32_t gTotalCacheMisses;
 #endif
@@ -192,11 +192,11 @@ static bool run_single_benchmark(const SkString& inputPath,
 
     benchmark.run(picture);
 
-#if LAZY_CACHE_STATS
+#if SK_LAZY_CACHE_STATS
     if (FLAGS_trackDeferredCaching) {
-        int32_t cacheHits = pool->fCacheHits;
-        int32_t cacheMisses = pool->fCacheMisses;
-        pool->fCacheHits = pool->fCacheMisses = 0;
+        int cacheHits = pool->getCacheHits();
+        int cacheMisses = pool->getCacheMisses();
+        pool->resetCacheHitsAndMisses();
         SkString hitString;
         hitString.printf("Cache hit rate: %f\n", (double) cacheHits / (cacheHits + cacheMisses));
         gLogger.logProgress(hitString);
@@ -435,7 +435,7 @@ int tool_main(int argc, char** argv) {
         gLogger.logError(err);
         return 1;
     }
-#if LAZY_CACHE_STATS
+#if SK_LAZY_CACHE_STATS
     if (FLAGS_trackDeferredCaching) {
         SkDebugf("Total cache hit rate: %f\n",
                  (double) gTotalCacheHits / (gTotalCacheHits + gTotalCacheMisses));