Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: src/core/SkCachedData.cpp

Issue 592843003: Add SkCachedData and use it for SkMipMap (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: use natural bools for state tracking Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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_priv.h"
9 #include "SkRefCnt.h"
10 #include "SkDiscardableMemory.h"
11
12 SkCachedData::SkCachedData(void* data, size_t size)
13 : fData(data)
14 , fSize(size)
15 , fRefCnt(1)
16 , fStorageType(kMalloc_StorageType)
17 , fInCache(false)
18 , fIsLocked(true)
19 {
20 fStorage.fMalloc = data;
21 }
22
23 SkCachedData::SkCachedData(size_t size, SkDiscardableMemory* dm)
24 : fData(dm->data())
25 , fSize(size)
26 , fRefCnt(1)
27 , fStorageType(kDiscardableMemory_StorageType)
28 , fInCache(false)
29 , fIsLocked(true)
30 {
31 fStorage.fDM = dm;
32 }
33
34 SkCachedData::~SkCachedData() {
35 switch (fStorageType) {
36 case kMalloc_StorageType:
37 sk_free(fStorage.fMalloc);
38 break;
39 case kDiscardableMemory_StorageType:
40 SkDELETE(fStorage.fDM);
41 break;
42 }
43 }
44
45 class SkCachedData::AutoMutexWritable {
46 public:
47 AutoMutexWritable(const SkCachedData* cd) : fCD(const_cast<SkCachedData*>(cd )) {
48 fCD->get_mutex().acquire();
49 fCD->validate();
50 }
51 ~AutoMutexWritable() {
52 fCD->validate();
53 fCD->get_mutex().release();
54 }
55
56 SkCachedData* get() { return fCD; }
57 SkCachedData* operator->() { return fCD; }
58
59 private:
60 SkCachedData* fCD;
61 };
62
63 void SkCachedData::internalRef(bool fromCache) const {
64 AutoMutexWritable writable(this);
mtklein 2014/09/27 14:47:49 I really like this pattern.
65
66 SkASSERT(!fromCache || !writable->fInCache); // we can only be in a cache once
67
68 if ((1 == writable->fRefCnt) && fInCache) {
69 writable->in_mutex_lock();
70 }
71
72 writable->fRefCnt += 1;
73 writable->fInCache |= fromCache;
mtklein 2014/09/27 14:47:49 Just a nit, but I'd go with ||= here. It really i
reed1 2014/09/27 17:25:58 ||= isn't legal afaik However, I did rewrite to u
74 }
75
76 bool SkCachedData::doInternalUnref(bool fromCache) const {
77 AutoMutexWritable writable(this);
78
79 switch (writable->fRefCnt) {
mtklein 2014/09/27 14:47:49 These guys might read better if you decrement firs
reed1 2014/09/27 17:25:58 Done.
80 case 1:
81 // we're going to be deleted, so we need to be unlocked (for Discard ableMemory)
82 if (writable->fIsLocked) {
83 writable->in_mutex_unlock();
84 }
85 break;
86 case 2:
87 if (fInCache && !fromCache) {
88 // If we're down to 1 owner, and that owner is the cache, this i t is safe
89 // to unlock (and mutate fData) even if the cache is in a differ ent thread,
90 // as the cache is NOT allowed to inspect or use fData.
91 writable->in_mutex_unlock();
92 }
93 break;
94 default:
95 break;
96 }
97
98 if (fromCache) {
99 SkASSERT(writable->fInCache);
100 writable->fInCache = false;
101 }
102
103 // return true when we need to be deleted
104 return 0 == --writable->fRefCnt;
105 }
106
107 void SkCachedData::internalUnref(bool fromCache) const {
108 if (this->doInternalUnref(fromCache)) {
109 // can't delete inside doInternalUnref, since it is locking a mutex (whi ch we own)
110 SkDELETE(this);
111 }
112 }
113
114 void SkCachedData::in_mutex_lock() {
115 this->assert_in_mutex();
116
117 SkASSERT(!fIsLocked);
118 fIsLocked = true;
119
120 switch (fStorageType) {
121 case kMalloc_StorageType:
122 this->setData(fStorage.fMalloc);
123 break;
124 case kDiscardableMemory_StorageType:
125 if (fStorage.fDM->lock()) {
126 this->setData(fStorage.fDM->data());
127 } else {
128 this->setData(NULL); // signal failure to lock, contents are g one
129 }
130 break;
131 }
132 }
133
134 void SkCachedData::in_mutex_unlock() {
135 this->assert_in_mutex();
136
137 SkASSERT(fIsLocked);
138 fIsLocked = false;
139
140 switch (fStorageType) {
141 case kMalloc_StorageType:
142 // nothing to do/check
143 break;
144 case kDiscardableMemory_StorageType:
145 if (fData) { // did the previous lock succeed?
146 fStorage.fDM->unlock();
147 }
148 break;
149 }
150 this->setData(NULL); // signal that we're in an unlocked state
151 }
152
153 #ifdef SK_DEBUG
154 void SkCachedData::validate() const {
155 if (fIsLocked) {
156 SkASSERT((fInCache && fRefCnt > 1) || !fInCache);
157 switch (fStorageType) {
158 case kMalloc_StorageType:
159 SkASSERT(fData == fStorage.fMalloc);
160 break;
161 case kDiscardableMemory_StorageType:
162 // fData can be null or the actual value, depending if DM's lock succeeded
163 break;
164 }
165 } else {
166 SkASSERT((fInCache && 1 == fRefCnt) || (0 == fRefCnt));
167 SkASSERT(NULL == fData);
168 }
169 }
170 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698