Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(695)

Unified Diff: src/lazy/SkDiscardableMemoryPool.cpp

Issue 103033002: Big Cleanup: SkBitmapFactory, SkLazyPixelRef, SkImageCache (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: rebase one last time Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/lazy/SkDiscardableMemoryPool.h ('k') | src/lazy/SkDiscardablePixelRef.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/lazy/SkDiscardableMemoryPool.cpp
diff --git a/src/lazy/SkDiscardableMemoryPool.cpp b/src/lazy/SkDiscardableMemoryPool.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..a1b2438a2bcc79a9c80eb3c49c7afc281cda112b
--- /dev/null
+++ b/src/lazy/SkDiscardableMemoryPool.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDiscardableMemoryPool.h"
+#include "SkOnce.h"
+
+// Note:
+// A PoolDiscardableMemory is memory that is counted in a pool.
+// A DiscardableMemoryPool is a pool of PoolDiscardableMemorys.
+
+/**
+ * A SkPoolDiscardableMemory is a SkDiscardableMemory that relies on
+ * a SkDiscardableMemoryPool object to manage the memory.
+ */
+class SkPoolDiscardableMemory : public SkDiscardableMemory {
+public:
+ SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
+ void* pointer, size_t bytes);
+ virtual ~SkPoolDiscardableMemory();
+ virtual bool lock() SK_OVERRIDE;
+ virtual void* data() SK_OVERRIDE;
+ virtual void unlock() SK_OVERRIDE;
+ friend class SkDiscardableMemoryPool;
+private:
+ SK_DECLARE_INTERNAL_LLIST_INTERFACE(SkPoolDiscardableMemory);
+ SkDiscardableMemoryPool* const fPool;
+ bool fLocked;
+ void* fPointer;
+ const size_t fBytes;
+};
+
+SkPoolDiscardableMemory::SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
+ void* pointer,
+ size_t bytes)
+ : fPool(pool)
+ , fLocked(true)
+ , fPointer(pointer)
+ , fBytes(bytes) {
+ SkASSERT(fPool != NULL);
+ SkASSERT(fPointer != NULL);
+ SkASSERT(fBytes > 0);
+ fPool->ref();
+}
+
+SkPoolDiscardableMemory::~SkPoolDiscardableMemory() {
+ fPool->free(this);
+ fPool->unref();
+}
+
+bool SkPoolDiscardableMemory::lock() {
+ return fPool->lock(this);
+}
+
+void* SkPoolDiscardableMemory::data() {
+ return fLocked ? fPointer : NULL;
+}
+
+void SkPoolDiscardableMemory::unlock() {
+ fPool->unlock(this);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+SkDiscardableMemoryPool::SkDiscardableMemoryPool(size_t budget,
+ SkBaseMutex* mutex)
+ : fMutex(mutex)
+ , fBudget(budget)
+ , fUsed(0) {
+ #if LAZY_CACHE_STATS
+ fCacheHits = 0;
+ fCacheMisses = 0;
+ #endif // LAZY_CACHE_STATS
+}
+SkDiscardableMemoryPool::~SkDiscardableMemoryPool() {
+ // SkPoolDiscardableMemory 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) {
+ // 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;
+ Iter iter;
+ SkPoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
+ while ((fUsed > budget) && (NULL != cur)) {
+ if (!cur->fLocked) {
+ SkPoolDiscardableMemory* dm = cur;
+ SkASSERT(dm->fPointer != NULL);
+ sk_free(dm->fPointer);
+ dm->fPointer = NULL;
+ SkASSERT(fUsed >= dm->fBytes);
+ fUsed -= dm->fBytes;
+ cur = iter.prev();
+ // Purged DMs are taken out of the list. This saves times
+ // looking them up. Purged DMs are NOT deleted.
+ fList.remove(dm);
+ } else {
+ cur = iter.prev();
+ }
+ }
+}
+
+SkDiscardableMemory* SkDiscardableMemoryPool::create(size_t bytes) {
+ void* addr = sk_malloc_flags(bytes, 0);
+ if (NULL == addr) {
+ return NULL;
+ }
+ SkPoolDiscardableMemory* dm = SkNEW_ARGS(SkPoolDiscardableMemory,
+ (this, addr, bytes));
+ SkAutoMutexAcquire autoMutexAcquire(fMutex);
+ fList.addToHead(dm);
+ fUsed += bytes;
+ this->dumpDownTo(fBudget);
+ return dm;
+}
+
+void SkDiscardableMemoryPool::free(SkPoolDiscardableMemory* dm) {
+ // This is called by dm's destructor.
+ if (dm->fPointer != NULL) {
+ SkAutoMutexAcquire autoMutexAcquire(fMutex);
+ sk_free(dm->fPointer);
+ dm->fPointer = NULL;
+ SkASSERT(fUsed >= dm->fBytes);
+ fUsed -= dm->fBytes;
+ fList.remove(dm);
+ } else {
+ SkASSERT(!fList.isInList(dm));
+ }
+}
+
+bool SkDiscardableMemoryPool::lock(SkPoolDiscardableMemory* dm) {
+ SkASSERT(dm != NULL);
+ if (NULL == dm->fPointer) {
+ #if LAZY_CACHE_STATS
+ SkAutoMutexAcquire autoMutexAcquire(fMutex);
+ ++fCacheMisses;
+ #endif // LAZY_CACHE_STATS
+ return false;
+ }
+ SkAutoMutexAcquire autoMutexAcquire(fMutex);
+ if (NULL == dm->fPointer) {
+ // May have been purged while waiting for lock.
+ #if LAZY_CACHE_STATS
+ ++fCacheMisses;
+ #endif // LAZY_CACHE_STATS
+ return false;
+ }
+ dm->fLocked = true;
+ fList.remove(dm);
+ fList.addToHead(dm);
+ #if LAZY_CACHE_STATS
+ ++fCacheHits;
+ #endif // LAZY_CACHE_STATS
+ return true;
+}
+
+void SkDiscardableMemoryPool::unlock(SkPoolDiscardableMemory* dm) {
+ SkASSERT(dm != NULL);
+ SkAutoMutexAcquire autoMutexAcquire(fMutex);
+ dm->fLocked = false;
+ this->dumpDownTo(fBudget);
+}
+
+size_t SkDiscardableMemoryPool::getRAMUsed() {
+ return fUsed;
+}
+void SkDiscardableMemoryPool::setRAMBudget(size_t budget) {
+ SkAutoMutexAcquire autoMutexAcquire(fMutex);
+ fBudget = budget;
+ this->dumpDownTo(fBudget);
+}
+void SkDiscardableMemoryPool::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* SkGetGlobalDiscardableMemoryPool() {
+ static SkDiscardableMemoryPool* gPool(NULL);
+ SK_DECLARE_STATIC_ONCE(create_pool_once);
+ SkOnce(&create_pool_once, create_pool, &gPool);
+ SkASSERT(NULL != gPool);
+ return gPool;
+}
+
+////////////////////////////////////////////////////////////////////////////////
« no previous file with comments | « src/lazy/SkDiscardableMemoryPool.h ('k') | src/lazy/SkDiscardablePixelRef.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698