19d93c2ebb31bf996905532446644f242339a774ereed/* 29d93c2ebb31bf996905532446644f242339a774ereed * Copyright 2014 Google Inc. 39d93c2ebb31bf996905532446644f242339a774ereed * 49d93c2ebb31bf996905532446644f242339a774ereed * Use of this source code is governed by a BSD-style license that can be 59d93c2ebb31bf996905532446644f242339a774ereed * found in the LICENSE file. 69d93c2ebb31bf996905532446644f242339a774ereed */ 79d93c2ebb31bf996905532446644f242339a774ereed 89d93c2ebb31bf996905532446644f242339a774ereed#include "SkCachedData.h" 99d93c2ebb31bf996905532446644f242339a774ereed#include "SkDiscardableMemory.h" 109d93c2ebb31bf996905532446644f242339a774ereed 119d93c2ebb31bf996905532446644f242339a774ereed//#define TRACK_CACHEDDATA_LIFETIME 129d93c2ebb31bf996905532446644f242339a774ereed 139d93c2ebb31bf996905532446644f242339a774ereed#ifdef TRACK_CACHEDDATA_LIFETIME 149d93c2ebb31bf996905532446644f242339a774ereedstatic int32_t gCachedDataCounter; 159d93c2ebb31bf996905532446644f242339a774ereed 169d93c2ebb31bf996905532446644f242339a774ereedstatic void inc() { 179d93c2ebb31bf996905532446644f242339a774ereed int32_t oldCount = sk_atomic_inc(&gCachedDataCounter); 189d93c2ebb31bf996905532446644f242339a774ereed SkDebugf("SkCachedData inc %d\n", oldCount + 1); 199d93c2ebb31bf996905532446644f242339a774ereed} 209d93c2ebb31bf996905532446644f242339a774ereed 219d93c2ebb31bf996905532446644f242339a774ereedstatic void dec() { 229d93c2ebb31bf996905532446644f242339a774ereed int32_t oldCount = sk_atomic_dec(&gCachedDataCounter); 239d93c2ebb31bf996905532446644f242339a774ereed SkDebugf("SkCachedData dec %d\n", oldCount - 1); 249d93c2ebb31bf996905532446644f242339a774ereed} 259d93c2ebb31bf996905532446644f242339a774ereed#else 269d93c2ebb31bf996905532446644f242339a774ereedstatic void inc() {} 279d93c2ebb31bf996905532446644f242339a774ereedstatic void dec() {} 289d93c2ebb31bf996905532446644f242339a774ereed#endif 299d93c2ebb31bf996905532446644f242339a774ereed 309d93c2ebb31bf996905532446644f242339a774ereedSkCachedData::SkCachedData(void* data, size_t size) 319d93c2ebb31bf996905532446644f242339a774ereed : fData(data) 329d93c2ebb31bf996905532446644f242339a774ereed , fSize(size) 339d93c2ebb31bf996905532446644f242339a774ereed , fRefCnt(1) 349d93c2ebb31bf996905532446644f242339a774ereed , fStorageType(kMalloc_StorageType) 359d93c2ebb31bf996905532446644f242339a774ereed , fInCache(false) 369d93c2ebb31bf996905532446644f242339a774ereed , fIsLocked(true) 379d93c2ebb31bf996905532446644f242339a774ereed{ 389d93c2ebb31bf996905532446644f242339a774ereed fStorage.fMalloc = data; 399d93c2ebb31bf996905532446644f242339a774ereed inc(); 409d93c2ebb31bf996905532446644f242339a774ereed} 419d93c2ebb31bf996905532446644f242339a774ereed 429d93c2ebb31bf996905532446644f242339a774ereedSkCachedData::SkCachedData(size_t size, SkDiscardableMemory* dm) 439d93c2ebb31bf996905532446644f242339a774ereed : fData(dm->data()) 449d93c2ebb31bf996905532446644f242339a774ereed , fSize(size) 459d93c2ebb31bf996905532446644f242339a774ereed , fRefCnt(1) 469d93c2ebb31bf996905532446644f242339a774ereed , fStorageType(kDiscardableMemory_StorageType) 479d93c2ebb31bf996905532446644f242339a774ereed , fInCache(false) 489d93c2ebb31bf996905532446644f242339a774ereed , fIsLocked(true) 499d93c2ebb31bf996905532446644f242339a774ereed{ 509d93c2ebb31bf996905532446644f242339a774ereed fStorage.fDM = dm; 519d93c2ebb31bf996905532446644f242339a774ereed inc(); 529d93c2ebb31bf996905532446644f242339a774ereed} 539d93c2ebb31bf996905532446644f242339a774ereed 549d93c2ebb31bf996905532446644f242339a774ereedSkCachedData::~SkCachedData() { 559d93c2ebb31bf996905532446644f242339a774ereed switch (fStorageType) { 569d93c2ebb31bf996905532446644f242339a774ereed case kMalloc_StorageType: 579d93c2ebb31bf996905532446644f242339a774ereed sk_free(fStorage.fMalloc); 589d93c2ebb31bf996905532446644f242339a774ereed break; 599d93c2ebb31bf996905532446644f242339a774ereed case kDiscardableMemory_StorageType: 602880df2609eba09b555ca37be04b6ad89290c765Tom Hudson delete fStorage.fDM; 619d93c2ebb31bf996905532446644f242339a774ereed break; 629d93c2ebb31bf996905532446644f242339a774ereed } 639d93c2ebb31bf996905532446644f242339a774ereed dec(); 649d93c2ebb31bf996905532446644f242339a774ereed} 659d93c2ebb31bf996905532446644f242339a774ereed 669d93c2ebb31bf996905532446644f242339a774ereedclass SkCachedData::AutoMutexWritable { 679d93c2ebb31bf996905532446644f242339a774ereedpublic: 689d93c2ebb31bf996905532446644f242339a774ereed AutoMutexWritable(const SkCachedData* cd) : fCD(const_cast<SkCachedData*>(cd)) { 699d93c2ebb31bf996905532446644f242339a774ereed fCD->fMutex.acquire(); 709d93c2ebb31bf996905532446644f242339a774ereed fCD->validate(); 719d93c2ebb31bf996905532446644f242339a774ereed } 729d93c2ebb31bf996905532446644f242339a774ereed ~AutoMutexWritable() { 739d93c2ebb31bf996905532446644f242339a774ereed fCD->validate(); 749d93c2ebb31bf996905532446644f242339a774ereed fCD->fMutex.release(); 759d93c2ebb31bf996905532446644f242339a774ereed } 769d93c2ebb31bf996905532446644f242339a774ereed 779d93c2ebb31bf996905532446644f242339a774ereed SkCachedData* get() { return fCD; } 789d93c2ebb31bf996905532446644f242339a774ereed SkCachedData* operator->() { return fCD; } 799d93c2ebb31bf996905532446644f242339a774ereed 809d93c2ebb31bf996905532446644f242339a774ereedprivate: 819d93c2ebb31bf996905532446644f242339a774ereed SkCachedData* fCD; 829d93c2ebb31bf996905532446644f242339a774ereed}; 839d93c2ebb31bf996905532446644f242339a774ereed 849d93c2ebb31bf996905532446644f242339a774ereedvoid SkCachedData::internalRef(bool fromCache) const { 859d93c2ebb31bf996905532446644f242339a774ereed AutoMutexWritable(this)->inMutexRef(fromCache); 869d93c2ebb31bf996905532446644f242339a774ereed} 879d93c2ebb31bf996905532446644f242339a774ereed 889d93c2ebb31bf996905532446644f242339a774ereedvoid SkCachedData::internalUnref(bool fromCache) const { 899d93c2ebb31bf996905532446644f242339a774ereed if (AutoMutexWritable(this)->inMutexUnref(fromCache)) { 909d93c2ebb31bf996905532446644f242339a774ereed // can't delete inside doInternalUnref, since it is locking a mutex (which we own) 912880df2609eba09b555ca37be04b6ad89290c765Tom Hudson delete this; 929d93c2ebb31bf996905532446644f242339a774ereed } 939d93c2ebb31bf996905532446644f242339a774ereed} 949d93c2ebb31bf996905532446644f242339a774ereed 959d93c2ebb31bf996905532446644f242339a774ereed/////////////////////////////////////////////////////////////////////////////////////////////////// 969d93c2ebb31bf996905532446644f242339a774ereed 979d93c2ebb31bf996905532446644f242339a774ereedvoid SkCachedData::inMutexRef(bool fromCache) { 989d93c2ebb31bf996905532446644f242339a774ereed if ((1 == fRefCnt) && fInCache) { 999d93c2ebb31bf996905532446644f242339a774ereed this->inMutexLock(); 1009d93c2ebb31bf996905532446644f242339a774ereed } 1019d93c2ebb31bf996905532446644f242339a774ereed 1029d93c2ebb31bf996905532446644f242339a774ereed fRefCnt += 1; 1039d93c2ebb31bf996905532446644f242339a774ereed if (fromCache) { 1049d93c2ebb31bf996905532446644f242339a774ereed SkASSERT(!fInCache); 1059d93c2ebb31bf996905532446644f242339a774ereed fInCache = true; 1069d93c2ebb31bf996905532446644f242339a774ereed } 1079d93c2ebb31bf996905532446644f242339a774ereed} 1089d93c2ebb31bf996905532446644f242339a774ereed 1099d93c2ebb31bf996905532446644f242339a774ereedbool SkCachedData::inMutexUnref(bool fromCache) { 1109d93c2ebb31bf996905532446644f242339a774ereed switch (--fRefCnt) { 1119d93c2ebb31bf996905532446644f242339a774ereed case 0: 1129d93c2ebb31bf996905532446644f242339a774ereed // we're going to be deleted, so we need to be unlocked (for DiscardableMemory) 1139d93c2ebb31bf996905532446644f242339a774ereed if (fIsLocked) { 1149d93c2ebb31bf996905532446644f242339a774ereed this->inMutexUnlock(); 1159d93c2ebb31bf996905532446644f242339a774ereed } 1169d93c2ebb31bf996905532446644f242339a774ereed break; 1179d93c2ebb31bf996905532446644f242339a774ereed case 1: 1189d93c2ebb31bf996905532446644f242339a774ereed if (fInCache && !fromCache) { 1199d93c2ebb31bf996905532446644f242339a774ereed // If we're down to 1 owner, and that owner is the cache, this it is safe 1209d93c2ebb31bf996905532446644f242339a774ereed // to unlock (and mutate fData) even if the cache is in a different thread, 1219d93c2ebb31bf996905532446644f242339a774ereed // as the cache is NOT allowed to inspect or use fData. 1229d93c2ebb31bf996905532446644f242339a774ereed this->inMutexUnlock(); 1239d93c2ebb31bf996905532446644f242339a774ereed } 1249d93c2ebb31bf996905532446644f242339a774ereed break; 1259d93c2ebb31bf996905532446644f242339a774ereed default: 1269d93c2ebb31bf996905532446644f242339a774ereed break; 1279d93c2ebb31bf996905532446644f242339a774ereed } 1289d93c2ebb31bf996905532446644f242339a774ereed 1299d93c2ebb31bf996905532446644f242339a774ereed if (fromCache) { 1309d93c2ebb31bf996905532446644f242339a774ereed SkASSERT(fInCache); 1319d93c2ebb31bf996905532446644f242339a774ereed fInCache = false; 1329d93c2ebb31bf996905532446644f242339a774ereed } 1339d93c2ebb31bf996905532446644f242339a774ereed 1349d93c2ebb31bf996905532446644f242339a774ereed // return true when we need to be deleted 1359d93c2ebb31bf996905532446644f242339a774ereed return 0 == fRefCnt; 1369d93c2ebb31bf996905532446644f242339a774ereed} 1379d93c2ebb31bf996905532446644f242339a774ereed 1389d93c2ebb31bf996905532446644f242339a774ereedvoid SkCachedData::inMutexLock() { 1399d93c2ebb31bf996905532446644f242339a774ereed fMutex.assertHeld(); 1409d93c2ebb31bf996905532446644f242339a774ereed 1419d93c2ebb31bf996905532446644f242339a774ereed SkASSERT(!fIsLocked); 1429d93c2ebb31bf996905532446644f242339a774ereed fIsLocked = true; 1439d93c2ebb31bf996905532446644f242339a774ereed 1449d93c2ebb31bf996905532446644f242339a774ereed switch (fStorageType) { 1459d93c2ebb31bf996905532446644f242339a774ereed case kMalloc_StorageType: 1469d93c2ebb31bf996905532446644f242339a774ereed this->setData(fStorage.fMalloc); 1479d93c2ebb31bf996905532446644f242339a774ereed break; 1489d93c2ebb31bf996905532446644f242339a774ereed case kDiscardableMemory_StorageType: 1499d93c2ebb31bf996905532446644f242339a774ereed if (fStorage.fDM->lock()) { 1509d93c2ebb31bf996905532446644f242339a774ereed void* ptr = fStorage.fDM->data(); 1519d93c2ebb31bf996905532446644f242339a774ereed SkASSERT(ptr); 1529d93c2ebb31bf996905532446644f242339a774ereed this->setData(ptr); 1539d93c2ebb31bf996905532446644f242339a774ereed } else { 1542880df2609eba09b555ca37be04b6ad89290c765Tom Hudson this->setData(nullptr); // signal failure to lock, contents are gone 1559d93c2ebb31bf996905532446644f242339a774ereed } 1569d93c2ebb31bf996905532446644f242339a774ereed break; 1579d93c2ebb31bf996905532446644f242339a774ereed } 1589d93c2ebb31bf996905532446644f242339a774ereed} 1599d93c2ebb31bf996905532446644f242339a774ereed 1609d93c2ebb31bf996905532446644f242339a774ereedvoid SkCachedData::inMutexUnlock() { 1619d93c2ebb31bf996905532446644f242339a774ereed fMutex.assertHeld(); 1629d93c2ebb31bf996905532446644f242339a774ereed 1639d93c2ebb31bf996905532446644f242339a774ereed SkASSERT(fIsLocked); 1649d93c2ebb31bf996905532446644f242339a774ereed fIsLocked = false; 1659d93c2ebb31bf996905532446644f242339a774ereed 1669d93c2ebb31bf996905532446644f242339a774ereed switch (fStorageType) { 1679d93c2ebb31bf996905532446644f242339a774ereed case kMalloc_StorageType: 1689d93c2ebb31bf996905532446644f242339a774ereed // nothing to do/check 1699d93c2ebb31bf996905532446644f242339a774ereed break; 1709d93c2ebb31bf996905532446644f242339a774ereed case kDiscardableMemory_StorageType: 1719d93c2ebb31bf996905532446644f242339a774ereed if (fData) { // did the previous lock succeed? 1729d93c2ebb31bf996905532446644f242339a774ereed fStorage.fDM->unlock(); 1739d93c2ebb31bf996905532446644f242339a774ereed } 1749d93c2ebb31bf996905532446644f242339a774ereed break; 1759d93c2ebb31bf996905532446644f242339a774ereed } 1762880df2609eba09b555ca37be04b6ad89290c765Tom Hudson this->setData(nullptr); // signal that we're in an unlocked state 1779d93c2ebb31bf996905532446644f242339a774ereed} 1789d93c2ebb31bf996905532446644f242339a774ereed 1799d93c2ebb31bf996905532446644f242339a774ereed/////////////////////////////////////////////////////////////////////////////////////////////////// 1809d93c2ebb31bf996905532446644f242339a774ereed 1819d93c2ebb31bf996905532446644f242339a774ereed#ifdef SK_DEBUG 1829d93c2ebb31bf996905532446644f242339a774ereedvoid SkCachedData::validate() const { 1839d93c2ebb31bf996905532446644f242339a774ereed if (fIsLocked) { 1849d93c2ebb31bf996905532446644f242339a774ereed SkASSERT((fInCache && fRefCnt > 1) || !fInCache); 1859d93c2ebb31bf996905532446644f242339a774ereed switch (fStorageType) { 1869d93c2ebb31bf996905532446644f242339a774ereed case kMalloc_StorageType: 1879d93c2ebb31bf996905532446644f242339a774ereed SkASSERT(fData == fStorage.fMalloc); 1889d93c2ebb31bf996905532446644f242339a774ereed break; 1899d93c2ebb31bf996905532446644f242339a774ereed case kDiscardableMemory_StorageType: 1909d93c2ebb31bf996905532446644f242339a774ereed // fData can be null or the actual value, depending if DM's lock succeeded 1919d93c2ebb31bf996905532446644f242339a774ereed break; 1929d93c2ebb31bf996905532446644f242339a774ereed } 1939d93c2ebb31bf996905532446644f242339a774ereed } else { 1949d93c2ebb31bf996905532446644f242339a774ereed SkASSERT((fInCache && 1 == fRefCnt) || (0 == fRefCnt)); 1952880df2609eba09b555ca37be04b6ad89290c765Tom Hudson SkASSERT(nullptr == fData); 1969d93c2ebb31bf996905532446644f242339a774ereed } 1979d93c2ebb31bf996905532446644f242339a774ereed} 1989d93c2ebb31bf996905532446644f242339a774ereed#endif 199