OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2013 Google Inc. | 2 * Copyright 2013 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkChecksum.h" | 8 #include "SkChecksum.h" |
9 #include "SkResourceCache.h" | 9 #include "SkResourceCache.h" |
10 #include "SkMipMap.h" | 10 #include "SkMipMap.h" |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 while (rec) { | 180 while (rec) { |
181 Rec* next = rec->fNext; | 181 Rec* next = rec->fNext; |
182 SkDELETE(rec); | 182 SkDELETE(rec); |
183 rec = next; | 183 rec = next; |
184 } | 184 } |
185 delete fHash; | 185 delete fHash; |
186 } | 186 } |
187 | 187 |
188 //////////////////////////////////////////////////////////////////////////////// | 188 //////////////////////////////////////////////////////////////////////////////// |
189 | 189 |
190 const SkResourceCache::Rec* SkResourceCache::findAndLock(const Key& key) { | 190 bool SkResourceCache::find(const Key& key, VisitorProc visitor, void* context) { |
191 Rec* rec = fHash->find(key); | 191 Rec* rec = fHash->find(key); |
192 if (rec) { | 192 if (rec) { |
193 this->moveToHead(rec); // for our LRU | 193 if (visitor(*rec, context)) { |
194 rec->fLockCount += 1; | 194 this->moveToHead(rec); // for our LRU |
| 195 return true; |
| 196 } else { |
| 197 this->remove(rec); // stale |
| 198 return false; |
| 199 } |
195 } | 200 } |
196 return rec; | 201 return false; |
197 } | |
198 | |
199 const SkResourceCache::Rec* SkResourceCache::addAndLock(Rec* rec) { | |
200 SkASSERT(rec); | |
201 // See if we already have this key (racy inserts, etc.) | |
202 const Rec* existing = this->findAndLock(rec->getKey()); | |
203 if (existing) { | |
204 SkDELETE(rec); | |
205 return existing; | |
206 } | |
207 | |
208 this->addToHead(rec); | |
209 SkASSERT(1 == rec->fLockCount); | |
210 fHash->add(rec); | |
211 // We may (now) be overbudget, so see if we need to purge something. | |
212 this->purgeAsNeeded(); | |
213 return rec; | |
214 } | 202 } |
215 | 203 |
216 void SkResourceCache::add(Rec* rec) { | 204 void SkResourceCache::add(Rec* rec) { |
217 SkASSERT(rec); | 205 SkASSERT(rec); |
218 // See if we already have this key (racy inserts, etc.) | 206 // See if we already have this key (racy inserts, etc.) |
219 const Rec* existing = this->findAndLock(rec->getKey()); | 207 Rec* existing = fHash->find(rec->getKey()); |
220 if (existing) { | 208 if (existing) { |
221 SkDELETE(rec); | 209 SkDELETE(rec); |
222 this->unlock(existing); | |
223 return; | 210 return; |
224 } | 211 } |
225 | 212 |
226 this->addToHead(rec); | 213 this->addToHead(rec); |
227 SkASSERT(1 == rec->fLockCount); | |
228 fHash->add(rec); | 214 fHash->add(rec); |
229 this->unlock(rec); | |
230 } | |
231 | 215 |
232 void SkResourceCache::unlock(SkResourceCache::ID id) { | 216 // since the new rec may push us over-budget, we perform a purge check now |
233 SkASSERT(id); | 217 this->purgeAsNeeded(); |
234 | |
235 #ifdef SK_DEBUG | |
236 { | |
237 bool found = false; | |
238 Rec* rec = fHead; | |
239 while (rec != NULL) { | |
240 if (rec == id) { | |
241 found = true; | |
242 break; | |
243 } | |
244 rec = rec->fNext; | |
245 } | |
246 SkASSERT(found); | |
247 } | |
248 #endif | |
249 const Rec* rec = id; | |
250 SkASSERT(rec->fLockCount > 0); | |
251 // We're under our lock, and we're the only possible mutator, so unconsting
is fine. | |
252 const_cast<Rec*>(rec)->fLockCount -= 1; | |
253 | |
254 // we may have been over-budget, but now have released something, so check | |
255 // if we should purge. | |
256 if (0 == rec->fLockCount) { | |
257 this->purgeAsNeeded(); | |
258 } | |
259 } | 218 } |
260 | 219 |
261 void SkResourceCache::remove(Rec* rec) { | 220 void SkResourceCache::remove(Rec* rec) { |
262 SkASSERT(0 == rec->fLockCount); | |
263 | |
264 size_t used = rec->bytesUsed(); | 221 size_t used = rec->bytesUsed(); |
265 SkASSERT(used <= fTotalBytesUsed); | 222 SkASSERT(used <= fTotalBytesUsed); |
266 | 223 |
267 this->detach(rec); | 224 this->detach(rec); |
268 fHash->remove(rec->getKey()); | 225 fHash->remove(rec->getKey()); |
269 | 226 |
270 SkDELETE(rec); | 227 SkDELETE(rec); |
271 | 228 |
272 fTotalBytesUsed -= used; | 229 fTotalBytesUsed -= used; |
273 fCount -= 1; | 230 fCount -= 1; |
(...skipping 11 matching lines...) Expand all Loading... |
285 byteLimit = fTotalByteLimit; | 242 byteLimit = fTotalByteLimit; |
286 } | 243 } |
287 | 244 |
288 Rec* rec = fTail; | 245 Rec* rec = fTail; |
289 while (rec) { | 246 while (rec) { |
290 if (!forcePurge && fTotalBytesUsed < byteLimit && fCount < countLimit) { | 247 if (!forcePurge && fTotalBytesUsed < byteLimit && fCount < countLimit) { |
291 break; | 248 break; |
292 } | 249 } |
293 | 250 |
294 Rec* prev = rec->fPrev; | 251 Rec* prev = rec->fPrev; |
295 if (0 == rec->fLockCount) { | 252 this->remove(rec); |
296 this->remove(rec); | |
297 } | |
298 rec = prev; | 253 rec = prev; |
299 } | 254 } |
300 } | 255 } |
301 | 256 |
302 size_t SkResourceCache::setTotalByteLimit(size_t newLimit) { | 257 size_t SkResourceCache::setTotalByteLimit(size_t newLimit) { |
303 size_t prevLimit = fTotalByteLimit; | 258 size_t prevLimit = fTotalByteLimit; |
304 fTotalByteLimit = newLimit; | 259 fTotalByteLimit = newLimit; |
305 if (newLimit < prevLimit) { | 260 if (newLimit < prevLimit) { |
306 this->purgeAsNeeded(); | 261 this->purgeAsNeeded(); |
307 } | 262 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 } | 365 } |
411 | 366 |
412 SkASSERT(0 == count); | 367 SkASSERT(0 == count); |
413 SkASSERT(0 == used); | 368 SkASSERT(0 == used); |
414 } | 369 } |
415 #endif | 370 #endif |
416 | 371 |
417 void SkResourceCache::dump() const { | 372 void SkResourceCache::dump() const { |
418 this->validate(); | 373 this->validate(); |
419 | 374 |
420 const Rec* rec = fHead; | 375 SkDebugf("SkResourceCache: count=%d bytes=%d %s\n", |
421 int locked = 0; | 376 fCount, fTotalBytesUsed, fDiscardableFactory ? "discardable" : "mal
loc"); |
422 while (rec) { | |
423 locked += rec->fLockCount > 0; | |
424 rec = rec->fNext; | |
425 } | |
426 | |
427 SkDebugf("SkResourceCache: count=%d bytes=%d locked=%d %s\n", | |
428 fCount, fTotalBytesUsed, locked, | |
429 fDiscardableFactory ? "discardable" : "malloc"); | |
430 } | 377 } |
431 | 378 |
432 size_t SkResourceCache::setSingleAllocationByteLimit(size_t newLimit) { | 379 size_t SkResourceCache::setSingleAllocationByteLimit(size_t newLimit) { |
433 size_t oldLimit = fSingleAllocationByteLimit; | 380 size_t oldLimit = fSingleAllocationByteLimit; |
434 fSingleAllocationByteLimit = newLimit; | 381 fSingleAllocationByteLimit = newLimit; |
435 return oldLimit; | 382 return oldLimit; |
436 } | 383 } |
437 | 384 |
438 size_t SkResourceCache::getSingleAllocationByteLimit() const { | 385 size_t SkResourceCache::getSingleAllocationByteLimit() const { |
439 return fSingleAllocationByteLimit; | 386 return fSingleAllocationByteLimit; |
(...skipping 23 matching lines...) Expand all Loading... |
463 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE | 410 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE |
464 gResourceCache = SkNEW_ARGS(SkResourceCache, (SkDiscardableMemory::Creat
e)); | 411 gResourceCache = SkNEW_ARGS(SkResourceCache, (SkDiscardableMemory::Creat
e)); |
465 #else | 412 #else |
466 gResourceCache = SkNEW_ARGS(SkResourceCache, (SK_DEFAULT_IMAGE_CACHE_LIM
IT)); | 413 gResourceCache = SkNEW_ARGS(SkResourceCache, (SK_DEFAULT_IMAGE_CACHE_LIM
IT)); |
467 #endif | 414 #endif |
468 atexit(cleanup_gResourceCache); | 415 atexit(cleanup_gResourceCache); |
469 } | 416 } |
470 return gResourceCache; | 417 return gResourceCache; |
471 } | 418 } |
472 | 419 |
473 void SkResourceCache::Unlock(SkResourceCache::ID id) { | |
474 SkAutoMutexAcquire am(gMutex); | |
475 get_cache()->unlock(id); | |
476 | |
477 // get_cache()->dump(); | |
478 } | |
479 | |
480 void SkResourceCache::Remove(SkResourceCache::ID id) { | |
481 SkAutoMutexAcquire am(gMutex); | |
482 SkASSERT(id); | |
483 | |
484 #ifdef SK_DEBUG | |
485 { | |
486 bool found = false; | |
487 Rec* rec = get_cache()->fHead; | |
488 while (rec != NULL) { | |
489 if (rec == id) { | |
490 found = true; | |
491 break; | |
492 } | |
493 rec = rec->fNext; | |
494 } | |
495 SkASSERT(found); | |
496 } | |
497 #endif | |
498 const Rec* rec = id; | |
499 get_cache()->remove(const_cast<Rec*>(rec)); | |
500 } | |
501 | |
502 size_t SkResourceCache::GetTotalBytesUsed() { | 420 size_t SkResourceCache::GetTotalBytesUsed() { |
503 SkAutoMutexAcquire am(gMutex); | 421 SkAutoMutexAcquire am(gMutex); |
504 return get_cache()->getTotalBytesUsed(); | 422 return get_cache()->getTotalBytesUsed(); |
505 } | 423 } |
506 | 424 |
507 size_t SkResourceCache::GetTotalByteLimit() { | 425 size_t SkResourceCache::GetTotalByteLimit() { |
508 SkAutoMutexAcquire am(gMutex); | 426 SkAutoMutexAcquire am(gMutex); |
509 return get_cache()->getTotalByteLimit(); | 427 return get_cache()->getTotalByteLimit(); |
510 } | 428 } |
511 | 429 |
(...skipping 20 matching lines...) Expand all Loading... |
532 size_t SkResourceCache::GetSingleAllocationByteLimit() { | 450 size_t SkResourceCache::GetSingleAllocationByteLimit() { |
533 SkAutoMutexAcquire am(gMutex); | 451 SkAutoMutexAcquire am(gMutex); |
534 return get_cache()->getSingleAllocationByteLimit(); | 452 return get_cache()->getSingleAllocationByteLimit(); |
535 } | 453 } |
536 | 454 |
537 void SkResourceCache::PurgeAll() { | 455 void SkResourceCache::PurgeAll() { |
538 SkAutoMutexAcquire am(gMutex); | 456 SkAutoMutexAcquire am(gMutex); |
539 return get_cache()->purgeAll(); | 457 return get_cache()->purgeAll(); |
540 } | 458 } |
541 | 459 |
542 const SkResourceCache::Rec* SkResourceCache::FindAndLock(const Key& key) { | 460 bool SkResourceCache::Find(const Key& key, VisitorProc visitor, void* context) { |
543 SkAutoMutexAcquire am(gMutex); | 461 SkAutoMutexAcquire am(gMutex); |
544 return get_cache()->findAndLock(key); | 462 return get_cache()->find(key, visitor, context); |
545 } | |
546 | |
547 const SkResourceCache::Rec* SkResourceCache::AddAndLock(Rec* rec) { | |
548 SkAutoMutexAcquire am(gMutex); | |
549 return get_cache()->addAndLock(rec); | |
550 } | 463 } |
551 | 464 |
552 void SkResourceCache::Add(Rec* rec) { | 465 void SkResourceCache::Add(Rec* rec) { |
553 SkAutoMutexAcquire am(gMutex); | 466 SkAutoMutexAcquire am(gMutex); |
554 get_cache()->add(rec); | 467 get_cache()->add(rec); |
555 } | 468 } |
556 | 469 |
557 /////////////////////////////////////////////////////////////////////////////// | 470 /////////////////////////////////////////////////////////////////////////////// |
558 | 471 |
559 #include "SkGraphics.h" | 472 #include "SkGraphics.h" |
(...skipping 15 matching lines...) Expand all Loading... |
575 } | 488 } |
576 | 489 |
577 size_t SkGraphics::SetResourceCacheSingleAllocationByteLimit(size_t newLimit) { | 490 size_t SkGraphics::SetResourceCacheSingleAllocationByteLimit(size_t newLimit) { |
578 return SkResourceCache::SetSingleAllocationByteLimit(newLimit); | 491 return SkResourceCache::SetSingleAllocationByteLimit(newLimit); |
579 } | 492 } |
580 | 493 |
581 void SkGraphics::PurgeResourceCache() { | 494 void SkGraphics::PurgeResourceCache() { |
582 return SkResourceCache::PurgeAll(); | 495 return SkResourceCache::PurgeAll(); |
583 } | 496 } |
584 | 497 |
OLD | NEW |