Index: src/core/SkCachedData.cpp |
diff --git a/src/core/SkCachedData.cpp b/src/core/SkCachedData.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..e9ab51d767b2aef00af999c04d8fd3e1b6fe9db0 |
--- /dev/null |
+++ b/src/core/SkCachedData.cpp |
@@ -0,0 +1,121 @@ |
+/* |
+ * 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(int refAmount) { |
+#ifdef SK_DEBUG |
+ SkASSERT(2 == refAmount || 3 == refAmount); |
+ if (3 == refAmount) { |
+ // assert that we are not already attached (i.e. the low-bit is 0) |
+ SkASSERT(0 == (fRefCnt & 1)); |
+ } |
+#endif |
+ |
+ const int32_t new_count = sk_atomic_add(&fRefCnt, refAmount) + refAmount; |
+ const int owners = new_count >> 1; |
+ const int in_cache = new_count & 1; |
+ |
+ SkASSERT(owners >= 2); |
+ |
+ if (2 == owners) { |
qiankun
2014/09/25 07:15:11
In some cases, owners may exceed 2 before SkCached
|
+ sk_membar_acquire__after_atomic_dec(); |
+ if (in_cache) { |
+ this->lock(); |
+ } |
+ } |
+} |
+ |
+void SkCachedData::internalUnref(int refAmount) { |
+#ifdef SK_DEBUG |
+ SkASSERT(2 == refAmount || 3 == refAmount); |
+ if (3 == refAmount) { |
+ // assert that we are already attached (i.e. the low-bit is 1) |
+ SkASSERT(1 == (fRefCnt & 1)); |
+ } |
+#endif |
+ |
+ const int32_t new_count = sk_atomic_add(&fRefCnt, -refAmount) - refAmount; |
+ const int owners = new_count >> 1; |
+ const int in_cache = new_count & 1; |
+ |
+ switch (owners) { |
+ case 0: |
+ sk_membar_acquire__after_atomic_dec(); |
+ SkDELETE(this); |
+ break; |
+ case 1: |
+ sk_membar_acquire__after_atomic_dec(); |
+ if (in_cache) { |
+ this->unlock(); |
+ } |
+ break; |
+ default: |
+ break; |
+ } |
+} |
+ |
+void SkCachedData::lock() { |
+ switch (fStorageType) { |
+ case kMalloc_StorageType: |
+ fData = fStorage.fMalloc; |
+ break; |
+ case kDiscardableMemory_StorageType: |
+ if (fStorage.fDM->lock()) { |
+ fData = fStorage.fDM->data(); |
+ } else { |
+ fData = NULL; // signal failure to lock, contents are gone |
+ } |
+ break; |
+ } |
+} |
+ |
+void SkCachedData::unlock() { |
+ switch (fStorageType) { |
+ case kMalloc_StorageType: |
+ // nothing to do/check |
+ break; |
+ case kDiscardableMemory_StorageType: |
+ if (fData) { // did the previous lock succeed? |
+ fStorage.fDM->unlock(); |
+ } |
+ break; |
+ } |
+ fData = NULL; // signal that we're in an unlocked state |
+} |
+ |