Coverage Report

Created: 2021-08-22 09:07

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