Chromium Code Reviews| 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 |
| +} |
| + |