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

Side by Side Diff: src/lazy/SkLruImageCache.cpp

Issue 103033002: Big Cleanup: SkBitmapFactory, SkLazyPixelRef, SkImageCache (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright 2013 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 "SkLruImageCache.h"
9
10 SK_DEFINE_INST_COUNT(SkImageCache)
11 SK_DEFINE_INST_COUNT(SkLruImageCache)
12
13 static intptr_t NextGenerationID() {
14 static intptr_t gNextID;
15 do {
16 gNextID++;
17 } while (SkImageCache::UNINITIALIZED_ID == gNextID);
18 return gNextID;
19 }
20
21 class CachedPixels : public SkNoncopyable {
22
23 public:
24 CachedPixels(size_t length)
25 : fLength(length)
26 , fID(NextGenerationID())
27 , fLocked(false) {
28 fAddr = sk_malloc_throw(length);
29 }
30
31 ~CachedPixels() {
32 sk_free(fAddr);
33 }
34
35 void* getData() { return fAddr; }
36
37 intptr_t getID() const { return fID; }
38
39 size_t getLength() const { return fLength; }
40
41 void lock() { SkASSERT(!fLocked); fLocked = true; }
42
43 void unlock() { SkASSERT(fLocked); fLocked = false; }
44
45 bool isLocked() const { return fLocked; }
46
47 private:
48 void* fAddr;
49 size_t fLength;
50 const intptr_t fID;
51 bool fLocked;
52 SK_DECLARE_INTERNAL_LLIST_INTERFACE(CachedPixels);
53 };
54
55 //////////////////////////////////////////////////////////////////////////////// ////
56
57 SkLruImageCache::SkLruImageCache(size_t budget)
58 : fRamBudget(budget)
59 , fRamUsed(0) {}
60
61 SkLruImageCache::~SkLruImageCache() {
62 // Don't worry about updating pointers. All will be deleted.
63 Iter iter;
64 CachedPixels* pixels = iter.init(fLRU, Iter::kTail_IterStart);
65 while (pixels != NULL) {
66 CachedPixels* prev = iter.prev();
67 SkASSERT(!pixels->isLocked());
68 #ifdef SK_DEBUG
69 fRamUsed -= pixels->getLength();
70 #endif
71 SkDELETE(pixels);
72 pixels = prev;
73 }
74 #ifdef SK_DEBUG
75 SkASSERT(fRamUsed == 0);
76 #endif
77 }
78
79 #ifdef SK_DEBUG
80 SkImageCache::MemoryStatus SkLruImageCache::getMemoryStatus(intptr_t ID) const {
81 if (SkImageCache::UNINITIALIZED_ID == ID) {
82 return SkImageCache::kFreed_MemoryStatus;
83 }
84 SkAutoMutexAcquire ac(&fMutex);
85 CachedPixels* pixels = this->findByID(ID);
86 if (NULL == pixels) {
87 return SkImageCache::kFreed_MemoryStatus;
88 }
89 if (pixels->isLocked()) {
90 return SkImageCache::kPinned_MemoryStatus;
91 }
92 return SkImageCache::kUnpinned_MemoryStatus;
93 }
94
95 void SkLruImageCache::purgeAllUnpinnedCaches() {
96 SkAutoMutexAcquire ac(&fMutex);
97 this->purgeTilAtOrBelow(0);
98 }
99 #endif
100
101 size_t SkLruImageCache::setImageCacheLimit(size_t newLimit) {
102 size_t oldLimit = fRamBudget;
103 SkAutoMutexAcquire ac(&fMutex);
104 fRamBudget = newLimit;
105 this->purgeIfNeeded();
106 return oldLimit;
107 }
108
109 void* SkLruImageCache::allocAndPinCache(size_t bytes, intptr_t* ID) {
110 SkAutoMutexAcquire ac(&fMutex);
111 CachedPixels* pixels = SkNEW_ARGS(CachedPixels, (bytes));
112 if (ID != NULL) {
113 *ID = pixels->getID();
114 }
115 pixels->lock();
116 fRamUsed += bytes;
117 fLRU.addToHead(pixels);
118 this->purgeIfNeeded();
119 return pixels->getData();
120 }
121
122 void* SkLruImageCache::pinCache(intptr_t ID, SkImageCache::DataStatus* status) {
123 SkASSERT(ID != SkImageCache::UNINITIALIZED_ID);
124 SkAutoMutexAcquire ac(&fMutex);
125 CachedPixels* pixels = this->findByID(ID);
126 if (NULL == pixels) {
127 return NULL;
128 }
129 if (pixels != fLRU.head()) {
130 fLRU.remove(pixels);
131 fLRU.addToHead(pixels);
132 }
133 SkASSERT(status != NULL);
134 // This cache will never return pinned memory whose data has been overwritte n.
135 *status = SkImageCache::kRetained_DataStatus;
136 pixels->lock();
137 return pixels->getData();
138 }
139
140 void SkLruImageCache::releaseCache(intptr_t ID) {
141 SkASSERT(ID != SkImageCache::UNINITIALIZED_ID);
142 SkAutoMutexAcquire ac(&fMutex);
143 CachedPixels* pixels = this->findByID(ID);
144 SkASSERT(pixels != NULL);
145 pixels->unlock();
146 this->purgeIfNeeded();
147 }
148
149 void SkLruImageCache::throwAwayCache(intptr_t ID) {
150 SkASSERT(ID != SkImageCache::UNINITIALIZED_ID);
151 SkAutoMutexAcquire ac(&fMutex);
152 CachedPixels* pixels = this->findByID(ID);
153 if (pixels != NULL) {
154 if (pixels->isLocked()) {
155 pixels->unlock();
156 }
157 this->removePixels(pixels);
158 }
159 }
160
161 void SkLruImageCache::removePixels(CachedPixels* pixels) {
162 // Mutex is already locked.
163 SkASSERT(!pixels->isLocked());
164 const size_t size = pixels->getLength();
165 SkASSERT(size <= fRamUsed);
166 fLRU.remove(pixels);
167 SkDELETE(pixels);
168 fRamUsed -= size;
169 }
170
171 CachedPixels* SkLruImageCache::findByID(intptr_t ID) const {
172 // Mutex is already locked.
173 Iter iter;
174 // Start from the head, most recently used.
175 CachedPixels* pixels = iter.init(fLRU, Iter::kHead_IterStart);
176 while (pixels != NULL) {
177 if (pixels->getID() == ID) {
178 return pixels;
179 }
180 pixels = iter.next();
181 }
182 return NULL;
183 }
184
185 void SkLruImageCache::purgeIfNeeded() {
186 // Mutex is already locked.
187 if (fRamBudget > 0) {
188 this->purgeTilAtOrBelow(fRamBudget);
189 }
190 }
191
192 void SkLruImageCache::purgeTilAtOrBelow(size_t limit) {
193 // Mutex is already locked.
194 if (fRamUsed > limit) {
195 Iter iter;
196 // Start from the tail, least recently used.
197 CachedPixels* pixels = iter.init(fLRU, Iter::kTail_IterStart);
198 while (pixels != NULL && fRamUsed > limit) {
199 CachedPixels* prev = iter.prev();
200 if (!pixels->isLocked()) {
201 this->removePixels(pixels);
202 }
203 pixels = prev;
204 }
205 }
206 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698