1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2014 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/private/SkMalloc.h" 9cb93a386Sopenharmony_ci#include "src/core/SkCachedData.h" 10cb93a386Sopenharmony_ci#include "src/core/SkDiscardableMemory.h" 11cb93a386Sopenharmony_ci 12cb93a386Sopenharmony_ciSkCachedData::SkCachedData(void* data, size_t size) 13cb93a386Sopenharmony_ci : fData(data) 14cb93a386Sopenharmony_ci , fSize(size) 15cb93a386Sopenharmony_ci , fRefCnt(1) 16cb93a386Sopenharmony_ci , fStorageType(kMalloc_StorageType) 17cb93a386Sopenharmony_ci , fInCache(false) 18cb93a386Sopenharmony_ci , fIsLocked(true) 19cb93a386Sopenharmony_ci{ 20cb93a386Sopenharmony_ci fStorage.fMalloc = data; 21cb93a386Sopenharmony_ci} 22cb93a386Sopenharmony_ci 23cb93a386Sopenharmony_ciSkCachedData::SkCachedData(size_t size, SkDiscardableMemory* dm) 24cb93a386Sopenharmony_ci : fData(dm->data()) 25cb93a386Sopenharmony_ci , fSize(size) 26cb93a386Sopenharmony_ci , fRefCnt(1) 27cb93a386Sopenharmony_ci , fStorageType(kDiscardableMemory_StorageType) 28cb93a386Sopenharmony_ci , fInCache(false) 29cb93a386Sopenharmony_ci , fIsLocked(true) 30cb93a386Sopenharmony_ci{ 31cb93a386Sopenharmony_ci fStorage.fDM = dm; 32cb93a386Sopenharmony_ci} 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ciSkCachedData::~SkCachedData() { 35cb93a386Sopenharmony_ci switch (fStorageType) { 36cb93a386Sopenharmony_ci case kMalloc_StorageType: 37cb93a386Sopenharmony_ci sk_free(fStorage.fMalloc); 38cb93a386Sopenharmony_ci break; 39cb93a386Sopenharmony_ci case kDiscardableMemory_StorageType: 40cb93a386Sopenharmony_ci delete fStorage.fDM; 41cb93a386Sopenharmony_ci break; 42cb93a386Sopenharmony_ci } 43cb93a386Sopenharmony_ci} 44cb93a386Sopenharmony_ci 45cb93a386Sopenharmony_ciclass SkCachedData::AutoMutexWritable { 46cb93a386Sopenharmony_cipublic: 47cb93a386Sopenharmony_ci AutoMutexWritable(const SkCachedData* cd) : fCD(const_cast<SkCachedData*>(cd)) { 48cb93a386Sopenharmony_ci fCD->fMutex.acquire(); 49cb93a386Sopenharmony_ci fCD->validate(); 50cb93a386Sopenharmony_ci } 51cb93a386Sopenharmony_ci ~AutoMutexWritable() { 52cb93a386Sopenharmony_ci fCD->validate(); 53cb93a386Sopenharmony_ci fCD->fMutex.release(); 54cb93a386Sopenharmony_ci } 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci SkCachedData* get() { return fCD; } 57cb93a386Sopenharmony_ci SkCachedData* operator->() { return fCD; } 58cb93a386Sopenharmony_ci 59cb93a386Sopenharmony_ciprivate: 60cb93a386Sopenharmony_ci SkCachedData* fCD; 61cb93a386Sopenharmony_ci}; 62cb93a386Sopenharmony_ci 63cb93a386Sopenharmony_civoid SkCachedData::internalRef(bool fromCache) const { 64cb93a386Sopenharmony_ci AutoMutexWritable(this)->inMutexRef(fromCache); 65cb93a386Sopenharmony_ci} 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_civoid SkCachedData::internalUnref(bool fromCache) const { 68cb93a386Sopenharmony_ci if (AutoMutexWritable(this)->inMutexUnref(fromCache)) { 69cb93a386Sopenharmony_ci // can't delete inside doInternalUnref, since it is locking a mutex (which we own) 70cb93a386Sopenharmony_ci delete this; 71cb93a386Sopenharmony_ci } 72cb93a386Sopenharmony_ci} 73cb93a386Sopenharmony_ci 74cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 75cb93a386Sopenharmony_ci 76cb93a386Sopenharmony_civoid SkCachedData::inMutexRef(bool fromCache) { 77cb93a386Sopenharmony_ci if ((1 == fRefCnt) && fInCache) { 78cb93a386Sopenharmony_ci this->inMutexLock(); 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci fRefCnt += 1; 82cb93a386Sopenharmony_ci if (fromCache) { 83cb93a386Sopenharmony_ci SkASSERT(!fInCache); 84cb93a386Sopenharmony_ci fInCache = true; 85cb93a386Sopenharmony_ci } 86cb93a386Sopenharmony_ci} 87cb93a386Sopenharmony_ci 88cb93a386Sopenharmony_cibool SkCachedData::inMutexUnref(bool fromCache) { 89cb93a386Sopenharmony_ci switch (--fRefCnt) { 90cb93a386Sopenharmony_ci case 0: 91cb93a386Sopenharmony_ci // we're going to be deleted, so we need to be unlocked (for DiscardableMemory) 92cb93a386Sopenharmony_ci if (fIsLocked) { 93cb93a386Sopenharmony_ci this->inMutexUnlock(); 94cb93a386Sopenharmony_ci } 95cb93a386Sopenharmony_ci break; 96cb93a386Sopenharmony_ci case 1: 97cb93a386Sopenharmony_ci if (fInCache && !fromCache) { 98cb93a386Sopenharmony_ci // If we're down to 1 owner, and that owner is the cache, this it is safe 99cb93a386Sopenharmony_ci // to unlock (and mutate fData) even if the cache is in a different thread, 100cb93a386Sopenharmony_ci // as the cache is NOT allowed to inspect or use fData. 101cb93a386Sopenharmony_ci this->inMutexUnlock(); 102cb93a386Sopenharmony_ci } 103cb93a386Sopenharmony_ci break; 104cb93a386Sopenharmony_ci default: 105cb93a386Sopenharmony_ci break; 106cb93a386Sopenharmony_ci } 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci if (fromCache) { 109cb93a386Sopenharmony_ci SkASSERT(fInCache); 110cb93a386Sopenharmony_ci fInCache = false; 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci 113cb93a386Sopenharmony_ci // return true when we need to be deleted 114cb93a386Sopenharmony_ci return 0 == fRefCnt; 115cb93a386Sopenharmony_ci} 116cb93a386Sopenharmony_ci 117cb93a386Sopenharmony_civoid SkCachedData::inMutexLock() { 118cb93a386Sopenharmony_ci fMutex.assertHeld(); 119cb93a386Sopenharmony_ci 120cb93a386Sopenharmony_ci SkASSERT(!fIsLocked); 121cb93a386Sopenharmony_ci fIsLocked = true; 122cb93a386Sopenharmony_ci 123cb93a386Sopenharmony_ci switch (fStorageType) { 124cb93a386Sopenharmony_ci case kMalloc_StorageType: 125cb93a386Sopenharmony_ci this->setData(fStorage.fMalloc); 126cb93a386Sopenharmony_ci break; 127cb93a386Sopenharmony_ci case kDiscardableMemory_StorageType: 128cb93a386Sopenharmony_ci if (fStorage.fDM->lock()) { 129cb93a386Sopenharmony_ci void* ptr = fStorage.fDM->data(); 130cb93a386Sopenharmony_ci SkASSERT(ptr); 131cb93a386Sopenharmony_ci this->setData(ptr); 132cb93a386Sopenharmony_ci } else { 133cb93a386Sopenharmony_ci this->setData(nullptr); // signal failure to lock, contents are gone 134cb93a386Sopenharmony_ci } 135cb93a386Sopenharmony_ci break; 136cb93a386Sopenharmony_ci } 137cb93a386Sopenharmony_ci} 138cb93a386Sopenharmony_ci 139cb93a386Sopenharmony_civoid SkCachedData::inMutexUnlock() { 140cb93a386Sopenharmony_ci fMutex.assertHeld(); 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_ci SkASSERT(fIsLocked); 143cb93a386Sopenharmony_ci fIsLocked = false; 144cb93a386Sopenharmony_ci 145cb93a386Sopenharmony_ci switch (fStorageType) { 146cb93a386Sopenharmony_ci case kMalloc_StorageType: 147cb93a386Sopenharmony_ci // nothing to do/check 148cb93a386Sopenharmony_ci break; 149cb93a386Sopenharmony_ci case kDiscardableMemory_StorageType: 150cb93a386Sopenharmony_ci if (fData) { // did the previous lock succeed? 151cb93a386Sopenharmony_ci fStorage.fDM->unlock(); 152cb93a386Sopenharmony_ci } 153cb93a386Sopenharmony_ci break; 154cb93a386Sopenharmony_ci } 155cb93a386Sopenharmony_ci this->setData(nullptr); // signal that we're in an unlocked state 156cb93a386Sopenharmony_ci} 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ci/////////////////////////////////////////////////////////////////////////////////////////////////// 159cb93a386Sopenharmony_ci 160cb93a386Sopenharmony_ci#ifdef SK_DEBUG 161cb93a386Sopenharmony_civoid SkCachedData::validate() const { 162cb93a386Sopenharmony_ci if (fIsLocked) { 163cb93a386Sopenharmony_ci SkASSERT((fInCache && fRefCnt > 1) || !fInCache); 164cb93a386Sopenharmony_ci switch (fStorageType) { 165cb93a386Sopenharmony_ci case kMalloc_StorageType: 166cb93a386Sopenharmony_ci SkASSERT(fData == fStorage.fMalloc); 167cb93a386Sopenharmony_ci break; 168cb93a386Sopenharmony_ci case kDiscardableMemory_StorageType: 169cb93a386Sopenharmony_ci // fData can be null or the actual value, depending if DM's lock succeeded 170cb93a386Sopenharmony_ci break; 171cb93a386Sopenharmony_ci } 172cb93a386Sopenharmony_ci } else { 173cb93a386Sopenharmony_ci SkASSERT((fInCache && 1 == fRefCnt) || (0 == fRefCnt)); 174cb93a386Sopenharmony_ci SkASSERT(nullptr == fData); 175cb93a386Sopenharmony_ci } 176cb93a386Sopenharmony_ci} 177cb93a386Sopenharmony_ci#endif 178