Coverage Report

Created: 2024-09-14 07:19

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