SkCachedData.h revision 9d93c2ebb31bf996905532446644f242339a774e
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#ifndef SkCachedData_DEFINED 9#define SkCachedData_DEFINED 10 11#include "SkThread.h" 12 13class SkDiscardableMemory; 14 15class SkCachedData : ::SkNoncopyable { 16public: 17 SkCachedData(void* mallocData, size_t size); 18 SkCachedData(size_t size, SkDiscardableMemory*); 19 virtual ~SkCachedData(); 20 21 size_t size() const { return fSize; } 22 const void* data() const { return fData; } 23 24 void* writable_data() { return fData; } 25 26 void ref() const { this->internalRef(false); } 27 void unref() const { this->internalUnref(false); } 28 29 int testing_only_getRefCnt() const { return fRefCnt; } 30 bool testing_only_isLocked() const { return fIsLocked; } 31 bool testing_only_isInCache() const { return fInCache; } 32 33protected: 34 // called when fData changes. could be NULL. 35 virtual void onDataChange(void* oldData, void* newData) {} 36 37private: 38 SkMutex fMutex; // could use a pool of these... 39 40 enum StorageType { 41 kDiscardableMemory_StorageType, 42 kMalloc_StorageType 43 }; 44 45 union { 46 SkDiscardableMemory* fDM; 47 void* fMalloc; 48 } fStorage; 49 void* fData; 50 size_t fSize; 51 int fRefCnt; // low-bit means we're owned by the cache 52 StorageType fStorageType; 53 bool fInCache; 54 bool fIsLocked; 55 56 void internalRef(bool fromCache) const; 57 void internalUnref(bool fromCache) const; 58 59 void inMutexRef(bool fromCache); 60 bool inMutexUnref(bool fromCache); // returns true if we should delete "this" 61 void inMutexLock(); 62 void inMutexUnlock(); 63 64 // called whenever our fData might change (lock or unlock) 65 void setData(void* newData) { 66 if (newData != fData) { 67 // notify our subclasses of the change 68 this->onDataChange(fData, newData); 69 fData = newData; 70 } 71 } 72 73 class AutoMutexWritable; 74 75public: 76#ifdef SK_DEBUG 77 void validate() const; 78#else 79 void validate() const {} 80#endif 81 82 /* 83 * Attaching a data to to a SkResourceCache (only one at a time) enables the data to be 84 * unlocked when the cache is the only owner, thus freeing it to be purged (assuming the 85 * data is backed by a SkDiscardableMemory). 86 * 87 * When attached, it also automatically attempts to "lock" the data when the first client 88 * ref's the data (typically from a find(key, visitor) call). 89 * 90 * Thus the data will always be "locked" when a non-cache has a ref on it (whether or not 91 * the lock succeeded to recover the memory -- check data() to see if it is NULL). 92 */ 93 94 /* 95 * Call when adding this instance to a SkResourceCache::Rec subclass 96 * (typically in the Rec's constructor). 97 */ 98 void attachToCacheAndRef() const { this->internalRef(true); } 99 100 /* 101 * Call when removing this instance from a SkResourceCache::Rec subclass 102 * (typically in the Rec's destructor). 103 */ 104 void detachFromCacheAndUnref() const { this->internalUnref(true); } 105}; 106 107#endif 108