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 | |
232 void SkResourceCache::unlock(SkResourceCache::ID id) { | |
233 SkASSERT(id); | |
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(); | |
reed1
2014/09/15 18:15:41
The bug in the new CL was that we forgot to "purge
danakj
2014/09/15 18:21:16
Where is the purge in this CL then? I don't see on
reed1
2014/09/15 18:22:49
Just wanted to post the original that I'm revertin
| |
258 } | |
259 } | 215 } |
260 | 216 |
261 void SkResourceCache::remove(Rec* rec) { | 217 void SkResourceCache::remove(Rec* rec) { |
262 SkASSERT(0 == rec->fLockCount); | |
danakj
2014/09/15 18:21:17
This seems reasonable to keep, while the fLockCoun
| |
263 | |
264 size_t used = rec->bytesUsed(); | 218 size_t used = rec->bytesUsed(); |
265 SkASSERT(used <= fTotalBytesUsed); | 219 SkASSERT(used <= fTotalBytesUsed); |
266 | 220 |
267 this->detach(rec); | 221 this->detach(rec); |
268 fHash->remove(rec->getKey()); | 222 fHash->remove(rec->getKey()); |
269 | 223 |
270 SkDELETE(rec); | 224 SkDELETE(rec); |
271 | 225 |
272 fTotalBytesUsed -= used; | 226 fTotalBytesUsed -= used; |
273 fCount -= 1; | 227 fCount -= 1; |
(...skipping 11 matching lines...) Expand all Loading... | |
285 byteLimit = fTotalByteLimit; | 239 byteLimit = fTotalByteLimit; |
286 } | 240 } |
287 | 241 |
288 Rec* rec = fTail; | 242 Rec* rec = fTail; |
289 while (rec) { | 243 while (rec) { |
290 if (!forcePurge && fTotalBytesUsed < byteLimit && fCount < countLimit) { | 244 if (!forcePurge && fTotalBytesUsed < byteLimit && fCount < countLimit) { |
291 break; | 245 break; |
292 } | 246 } |
293 | 247 |
294 Rec* prev = rec->fPrev; | 248 Rec* prev = rec->fPrev; |
295 if (0 == rec->fLockCount) { | 249 this->remove(rec); |
296 this->remove(rec); | |
297 } | |
298 rec = prev; | 250 rec = prev; |
299 } | 251 } |
300 } | 252 } |
301 | 253 |
302 size_t SkResourceCache::setTotalByteLimit(size_t newLimit) { | 254 size_t SkResourceCache::setTotalByteLimit(size_t newLimit) { |
303 size_t prevLimit = fTotalByteLimit; | 255 size_t prevLimit = fTotalByteLimit; |
304 fTotalByteLimit = newLimit; | 256 fTotalByteLimit = newLimit; |
305 if (newLimit < prevLimit) { | 257 if (newLimit < prevLimit) { |
306 this->purgeAsNeeded(); | 258 this->purgeAsNeeded(); |
307 } | 259 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
410 } | 362 } |
411 | 363 |
412 SkASSERT(0 == count); | 364 SkASSERT(0 == count); |
413 SkASSERT(0 == used); | 365 SkASSERT(0 == used); |
414 } | 366 } |
415 #endif | 367 #endif |
416 | 368 |
417 void SkResourceCache::dump() const { | 369 void SkResourceCache::dump() const { |
418 this->validate(); | 370 this->validate(); |
419 | 371 |
420 const Rec* rec = fHead; | 372 SkDebugf("SkResourceCache: count=%d bytes=%d %s\n", |
421 int locked = 0; | 373 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 } | 374 } |
431 | 375 |
432 size_t SkResourceCache::setSingleAllocationByteLimit(size_t newLimit) { | 376 size_t SkResourceCache::setSingleAllocationByteLimit(size_t newLimit) { |
433 size_t oldLimit = fSingleAllocationByteLimit; | 377 size_t oldLimit = fSingleAllocationByteLimit; |
434 fSingleAllocationByteLimit = newLimit; | 378 fSingleAllocationByteLimit = newLimit; |
435 return oldLimit; | 379 return oldLimit; |
436 } | 380 } |
437 | 381 |
438 size_t SkResourceCache::getSingleAllocationByteLimit() const { | 382 size_t SkResourceCache::getSingleAllocationByteLimit() const { |
439 return fSingleAllocationByteLimit; | 383 return fSingleAllocationByteLimit; |
(...skipping 23 matching lines...) Expand all Loading... | |
463 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE | 407 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE |
464 gResourceCache = SkNEW_ARGS(SkResourceCache, (SkDiscardableMemory::Creat e)); | 408 gResourceCache = SkNEW_ARGS(SkResourceCache, (SkDiscardableMemory::Creat e)); |
465 #else | 409 #else |
466 gResourceCache = SkNEW_ARGS(SkResourceCache, (SK_DEFAULT_IMAGE_CACHE_LIM IT)); | 410 gResourceCache = SkNEW_ARGS(SkResourceCache, (SK_DEFAULT_IMAGE_CACHE_LIM IT)); |
467 #endif | 411 #endif |
468 atexit(cleanup_gResourceCache); | 412 atexit(cleanup_gResourceCache); |
469 } | 413 } |
470 return gResourceCache; | 414 return gResourceCache; |
471 } | 415 } |
472 | 416 |
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() { | 417 size_t SkResourceCache::GetTotalBytesUsed() { |
503 SkAutoMutexAcquire am(gMutex); | 418 SkAutoMutexAcquire am(gMutex); |
504 return get_cache()->getTotalBytesUsed(); | 419 return get_cache()->getTotalBytesUsed(); |
505 } | 420 } |
506 | 421 |
507 size_t SkResourceCache::GetTotalByteLimit() { | 422 size_t SkResourceCache::GetTotalByteLimit() { |
508 SkAutoMutexAcquire am(gMutex); | 423 SkAutoMutexAcquire am(gMutex); |
509 return get_cache()->getTotalByteLimit(); | 424 return get_cache()->getTotalByteLimit(); |
510 } | 425 } |
511 | 426 |
(...skipping 20 matching lines...) Expand all Loading... | |
532 size_t SkResourceCache::GetSingleAllocationByteLimit() { | 447 size_t SkResourceCache::GetSingleAllocationByteLimit() { |
533 SkAutoMutexAcquire am(gMutex); | 448 SkAutoMutexAcquire am(gMutex); |
534 return get_cache()->getSingleAllocationByteLimit(); | 449 return get_cache()->getSingleAllocationByteLimit(); |
535 } | 450 } |
536 | 451 |
537 void SkResourceCache::PurgeAll() { | 452 void SkResourceCache::PurgeAll() { |
538 SkAutoMutexAcquire am(gMutex); | 453 SkAutoMutexAcquire am(gMutex); |
539 return get_cache()->purgeAll(); | 454 return get_cache()->purgeAll(); |
540 } | 455 } |
541 | 456 |
542 const SkResourceCache::Rec* SkResourceCache::FindAndLock(const Key& key) { | 457 bool SkResourceCache::Find(const Key& key, VisitorProc visitor, void* context) { |
543 SkAutoMutexAcquire am(gMutex); | 458 SkAutoMutexAcquire am(gMutex); |
544 return get_cache()->findAndLock(key); | 459 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 } | 460 } |
551 | 461 |
552 void SkResourceCache::Add(Rec* rec) { | 462 void SkResourceCache::Add(Rec* rec) { |
553 SkAutoMutexAcquire am(gMutex); | 463 SkAutoMutexAcquire am(gMutex); |
554 get_cache()->add(rec); | 464 get_cache()->add(rec); |
555 } | 465 } |
556 | 466 |
557 /////////////////////////////////////////////////////////////////////////////// | 467 /////////////////////////////////////////////////////////////////////////////// |
558 | 468 |
559 #include "SkGraphics.h" | 469 #include "SkGraphics.h" |
(...skipping 15 matching lines...) Expand all Loading... | |
575 } | 485 } |
576 | 486 |
577 size_t SkGraphics::SetResourceCacheSingleAllocationByteLimit(size_t newLimit) { | 487 size_t SkGraphics::SetResourceCacheSingleAllocationByteLimit(size_t newLimit) { |
578 return SkResourceCache::SetSingleAllocationByteLimit(newLimit); | 488 return SkResourceCache::SetSingleAllocationByteLimit(newLimit); |
579 } | 489 } |
580 | 490 |
581 void SkGraphics::PurgeResourceCache() { | 491 void SkGraphics::PurgeResourceCache() { |
582 return SkResourceCache::PurgeAll(); | 492 return SkResourceCache::PurgeAll(); |
583 } | 493 } |
584 | 494 |
OLD | NEW |