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