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

Unified Diff: src/core/SkCachedData.cpp

Issue 592843003: Add SkCachedData and use it for SkMipMap (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years, 3 months 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
Index: src/core/SkCachedData.cpp
diff --git a/src/core/SkCachedData.cpp b/src/core/SkCachedData.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..5142c523962c7c84b1fbdae272637b917e5b9c4a
--- /dev/null
+++ b/src/core/SkCachedData.cpp
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2014 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkCachedData_priv.h"
+#include "SkRefCnt.h"
+#include "SkDiscardableMemory.h"
+
+SkCachedData::SkCachedData(void* data, size_t size)
+ : fData(data)
+ , fSize(size)
+ , fRefCnt(2) // 1 owner, not in cache
+{
+ fStorage.fMalloc = data;
+ fStorageType = kMalloc_StorageType;
+}
+
+SkCachedData::SkCachedData(size_t size, SkDiscardableMemory* dm)
+ : fData(dm->data())
+ , fSize(size)
+ , fRefCnt(2) // 1 owner, not in cache
+{
+ fStorage.fDM = dm;
+ fStorageType = kDiscardableMemory_StorageType;
+}
+
+SkCachedData::~SkCachedData() {
+ switch (fStorageType) {
+ case kMalloc_StorageType:
+ sk_free(fStorage.fMalloc);
+ break;
+ case kDiscardableMemory_StorageType:
+ SkDELETE(fStorage.fDM);
+ break;
+ }
+}
+
+void SkCachedData::internalRef(bool fromCache) const {
+ SkCachedData* writable = const_cast<SkCachedData*>(this);
+ SkAutoMutexAcquire ama(writable->get_mutex());
+
+ int32_t amount;
+ if (fromCache) {
+ // assert that we are not already attached (i.e. the low-bit is 0)
+ SkASSERT(0 == (writable->fRefCnt & 1));
+ amount = 3;
+ } else {
+ // from client
+ amount = 2;
+ }
+
+ const int32_t new_count = (writable->fRefCnt += amount);
+ const int new_owners = new_count >> 1;
+ const int in_cache = new_count & 1;
+
+ SkASSERT(new_owners >= 2);
+
+ if (2 == new_owners && !fromCache) {
+ if (in_cache) {
+ writable->in_mutex_lock();
+ }
+ }
+}
+
+bool SkCachedData::doInternalUnref(bool fromCache) const {
+ SkCachedData* writable = const_cast<SkCachedData*>(this);
+ SkAutoMutexAcquire ama(writable->get_mutex());
+
+ int32_t amount;
+ if (fromCache) {
+ // assert that we are already attached (i.e. the low-bit is 1)
+ SkASSERT(1 == (fRefCnt & 1));
+ amount = 3;
+ } else {
+ // from client
+ amount = 2;
+ }
+
+ const int32_t new_count = (writable->fRefCnt -= amount);
+ const int new_owners = new_count >> 1;
+ const int in_cache = new_count & 1;
+
+ switch (new_owners) {
+ case 0:
+ writable->in_mutex_prepareToDelete();
+ break;
+ case 1:
+ if (in_cache) {
+ // If we're down to 1 owner, and that owner is the cache, this it is safe
+ // to unlock (and mutate fData) even if the cache is in a different thread,
+ // as the cache is NOT allowed to inspect or use fData.
+ writable->in_mutex_unlock();
+ }
+ break;
+ default:
+ break;
+ }
+ return 0 == new_owners;
+}
+
+void SkCachedData::internalUnref(bool fromCache) const {
+ if (this->doInternalUnref(fromCache)) {
+ // can't delete inside doInternalUnref, since it is locking a mutex (which we own)
+ SkDELETE(this);
+ }
+}
+
+void SkCachedData::in_mutex_lock() {
+ this->assert_in_mutex();
+
+ switch (fStorageType) {
+ case kMalloc_StorageType:
+ this->setData(fStorage.fMalloc);
+ break;
+ case kDiscardableMemory_StorageType:
+ if (fStorage.fDM->lock()) {
+ this->setData(fStorage.fDM->data());
+ } else {
+ this->setData(NULL); // signal failure to lock, contents are gone
+ }
+ break;
+ }
+}
+
+void SkCachedData::in_mutex_unlock() {
+ this->assert_in_mutex();
+
+ switch (fStorageType) {
+ case kMalloc_StorageType:
+ // nothing to do/check
+ break;
+ case kDiscardableMemory_StorageType:
+ if (fData) { // did the previous lock succeed?
+ fStorage.fDM->unlock();
+ }
+ break;
+ }
+ this->setData(NULL); // signal that we're in an unlocked state
+}
+
+void SkCachedData::in_mutex_prepareToDelete() {
+ this->assert_in_mutex();
+
+ switch (fStorageType) {
+ case kMalloc_StorageType:
+ // nothing to do/check
+ break;
+ case kDiscardableMemory_StorageType:
+ // discardable request that it be unlocked before being deleted
+ if (fData) {
+ fStorage.fDM->unlock();
+ }
+ break;
+ }
+}
+

Powered by Google App Engine
This is Rietveld 408576698