LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkCachedData.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 93 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13