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

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

Powered by Google App Engine
This is Rietveld 408576698