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