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

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: 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(2) // 1 owner, not in cache
16 {
17 fStorage.fMalloc = data;
18 fStorageType = kMalloc_StorageType;
19 }
20
21 SkCachedData::SkCachedData(size_t size, SkDiscardableMemory* dm)
22 : fData(dm->data())
23 , fSize(size)
24 , fRefCnt(2) // 1 owner, not in cache
25 {
26 fStorage.fDM = dm;
27 fStorageType = kDiscardableMemory_StorageType;
28 }
29
30 SkCachedData::~SkCachedData() {
31 switch (fStorageType) {
32 case kMalloc_StorageType:
33 sk_free(fStorage.fMalloc);
34 break;
35 case kDiscardableMemory_StorageType:
36 SkDELETE(fStorage.fDM);
37 break;
38 }
39 }
40
41 void SkCachedData::internalRef(bool fromCache) const {
42 SkCachedData* writable = const_cast<SkCachedData*>(this);
43 SkAutoMutexAcquire ama(writable->get_mutex());
44
45 int32_t amount;
46 if (fromCache) {
47 // assert that we are not already attached (i.e. the low-bit is 0)
48 SkASSERT(0 == (writable->fRefCnt & 1));
49 amount = 3;
50 } else {
51 // from client
52 amount = 2;
53 }
54
55 const int32_t new_count = (writable->fRefCnt += amount);
56 const int new_owners = new_count >> 1;
57 const int in_cache = new_count & 1;
58
59 SkASSERT(new_owners >= 2);
60
61 if (2 == new_owners && !fromCache) {
62 if (in_cache) {
63 writable->in_mutex_lock();
64 }
65 }
66 }
67
68 bool SkCachedData::doInternalUnref(bool fromCache) const {
69 SkCachedData* writable = const_cast<SkCachedData*>(this);
70 SkAutoMutexAcquire ama(writable->get_mutex());
71
72 int32_t amount;
73 if (fromCache) {
74 // assert that we are already attached (i.e. the low-bit is 1)
75 SkASSERT(1 == (fRefCnt & 1));
76 amount = 3;
77 } else {
78 // from client
79 amount = 2;
80 }
81
82 const int32_t new_count = (writable->fRefCnt -= amount);
83 const int new_owners = new_count >> 1;
84 const int in_cache = new_count & 1;
85
86 switch (new_owners) {
87 case 0:
88 writable->in_mutex_prepareToDelete();
89 break;
90 case 1:
91 if (in_cache) {
92 // If we're down to 1 owner, and that owner is the cache, this i t is safe
93 // to unlock (and mutate fData) even if the cache is in a differ ent thread,
94 // as the cache is NOT allowed to inspect or use fData.
95 writable->in_mutex_unlock();
96 }
97 break;
98 default:
99 break;
100 }
101 return 0 == new_owners;
102 }
103
104 void SkCachedData::internalUnref(bool fromCache) const {
105 if (this->doInternalUnref(fromCache)) {
106 // can't delete inside doInternalUnref, since it is locking a mutex (whi ch we own)
107 SkDELETE(this);
108 }
109 }
110
111 void SkCachedData::in_mutex_lock() {
112 this->assert_in_mutex();
113
114 switch (fStorageType) {
115 case kMalloc_StorageType:
116 this->setData(fStorage.fMalloc);
117 break;
118 case kDiscardableMemory_StorageType:
119 if (fStorage.fDM->lock()) {
120 this->setData(fStorage.fDM->data());
121 } else {
122 this->setData(NULL); // signal failure to lock, contents are g one
123 }
124 break;
125 }
126 }
127
128 void SkCachedData::in_mutex_unlock() {
129 this->assert_in_mutex();
130
131 switch (fStorageType) {
132 case kMalloc_StorageType:
133 // nothing to do/check
134 break;
135 case kDiscardableMemory_StorageType:
136 if (fData) { // did the previous lock succeed?
137 fStorage.fDM->unlock();
138 }
139 break;
140 }
141 this->setData(NULL); // signal that we're in an unlocked state
142 }
143
144 void SkCachedData::in_mutex_prepareToDelete() {
145 this->assert_in_mutex();
146
147 switch (fStorageType) {
148 case kMalloc_StorageType:
149 // nothing to do/check
150 break;
151 case kDiscardableMemory_StorageType:
152 // discardable request that it be unlocked before being deleted
153 if (fData) {
154 fStorage.fDM->unlock();
155 }
156 break;
157 }
158 }
159
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698