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 bool SkResourceCache::find(const Key& key, VisitorProc visitor, void* context) { | 190 const SkResourceCache::Rec* SkResourceCache::findAndLock(const Key& key) { |
191 Rec* rec = fHash->find(key); | 191 Rec* rec = fHash->find(key); |
192 if (rec) { | 192 if (rec) { |
193 if (visitor(*rec, context)) { | 193 this->moveToHead(rec); // for our LRU |
194 this->moveToHead(rec); // for our LRU | 194 rec->fLockCount += 1; |
195 return true; | |
196 } else { | |
197 this->remove(rec); // stale | |
198 return false; | |
199 } | |
200 } | 195 } |
201 return false; | 196 return rec; |
| 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; |
202 } | 214 } |
203 | 215 |
204 void SkResourceCache::add(Rec* rec) { | 216 void SkResourceCache::add(Rec* rec) { |
205 SkASSERT(rec); | 217 SkASSERT(rec); |
206 // See if we already have this key (racy inserts, etc.) | 218 // See if we already have this key (racy inserts, etc.) |
207 Rec* existing = fHash->find(rec->getKey()); | 219 const Rec* existing = this->findAndLock(rec->getKey()); |
208 if (existing) { | 220 if (existing) { |
209 SkDELETE(rec); | 221 SkDELETE(rec); |
| 222 this->unlock(existing); |
210 return; | 223 return; |
211 } | 224 } |
212 | 225 |
213 this->addToHead(rec); | 226 this->addToHead(rec); |
| 227 SkASSERT(1 == rec->fLockCount); |
214 fHash->add(rec); | 228 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(); |
| 258 } |
215 } | 259 } |
216 | 260 |
217 void SkResourceCache::remove(Rec* rec) { | 261 void SkResourceCache::remove(Rec* rec) { |
| 262 SkASSERT(0 == rec->fLockCount); |
| 263 |
218 size_t used = rec->bytesUsed(); | 264 size_t used = rec->bytesUsed(); |
219 SkASSERT(used <= fTotalBytesUsed); | 265 SkASSERT(used <= fTotalBytesUsed); |
220 | 266 |
221 this->detach(rec); | 267 this->detach(rec); |
222 fHash->remove(rec->getKey()); | 268 fHash->remove(rec->getKey()); |
223 | 269 |
224 SkDELETE(rec); | 270 SkDELETE(rec); |
225 | 271 |
226 fTotalBytesUsed -= used; | 272 fTotalBytesUsed -= used; |
227 fCount -= 1; | 273 fCount -= 1; |
(...skipping 11 matching lines...) Expand all Loading... |
239 byteLimit = fTotalByteLimit; | 285 byteLimit = fTotalByteLimit; |
240 } | 286 } |
241 | 287 |
242 Rec* rec = fTail; | 288 Rec* rec = fTail; |
243 while (rec) { | 289 while (rec) { |
244 if (!forcePurge && fTotalBytesUsed < byteLimit && fCount < countLimit) { | 290 if (!forcePurge && fTotalBytesUsed < byteLimit && fCount < countLimit) { |
245 break; | 291 break; |
246 } | 292 } |
247 | 293 |
248 Rec* prev = rec->fPrev; | 294 Rec* prev = rec->fPrev; |
249 this->remove(rec); | 295 if (0 == rec->fLockCount) { |
| 296 this->remove(rec); |
| 297 } |
250 rec = prev; | 298 rec = prev; |
251 } | 299 } |
252 } | 300 } |
253 | 301 |
254 size_t SkResourceCache::setTotalByteLimit(size_t newLimit) { | 302 size_t SkResourceCache::setTotalByteLimit(size_t newLimit) { |
255 size_t prevLimit = fTotalByteLimit; | 303 size_t prevLimit = fTotalByteLimit; |
256 fTotalByteLimit = newLimit; | 304 fTotalByteLimit = newLimit; |
257 if (newLimit < prevLimit) { | 305 if (newLimit < prevLimit) { |
258 this->purgeAsNeeded(); | 306 this->purgeAsNeeded(); |
259 } | 307 } |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
362 } | 410 } |
363 | 411 |
364 SkASSERT(0 == count); | 412 SkASSERT(0 == count); |
365 SkASSERT(0 == used); | 413 SkASSERT(0 == used); |
366 } | 414 } |
367 #endif | 415 #endif |
368 | 416 |
369 void SkResourceCache::dump() const { | 417 void SkResourceCache::dump() const { |
370 this->validate(); | 418 this->validate(); |
371 | 419 |
372 SkDebugf("SkResourceCache: count=%d bytes=%d %s\n", | 420 const Rec* rec = fHead; |
373 fCount, fTotalBytesUsed, fDiscardableFactory ? "discardable" : "mal
loc"); | 421 int locked = 0; |
| 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"); |
374 } | 430 } |
375 | 431 |
376 size_t SkResourceCache::setSingleAllocationByteLimit(size_t newLimit) { | 432 size_t SkResourceCache::setSingleAllocationByteLimit(size_t newLimit) { |
377 size_t oldLimit = fSingleAllocationByteLimit; | 433 size_t oldLimit = fSingleAllocationByteLimit; |
378 fSingleAllocationByteLimit = newLimit; | 434 fSingleAllocationByteLimit = newLimit; |
379 return oldLimit; | 435 return oldLimit; |
380 } | 436 } |
381 | 437 |
382 size_t SkResourceCache::getSingleAllocationByteLimit() const { | 438 size_t SkResourceCache::getSingleAllocationByteLimit() const { |
383 return fSingleAllocationByteLimit; | 439 return fSingleAllocationByteLimit; |
(...skipping 23 matching lines...) Expand all Loading... |
407 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE | 463 #ifdef SK_USE_DISCARDABLE_SCALEDIMAGECACHE |
408 gResourceCache = SkNEW_ARGS(SkResourceCache, (SkDiscardableMemory::Creat
e)); | 464 gResourceCache = SkNEW_ARGS(SkResourceCache, (SkDiscardableMemory::Creat
e)); |
409 #else | 465 #else |
410 gResourceCache = SkNEW_ARGS(SkResourceCache, (SK_DEFAULT_IMAGE_CACHE_LIM
IT)); | 466 gResourceCache = SkNEW_ARGS(SkResourceCache, (SK_DEFAULT_IMAGE_CACHE_LIM
IT)); |
411 #endif | 467 #endif |
412 atexit(cleanup_gResourceCache); | 468 atexit(cleanup_gResourceCache); |
413 } | 469 } |
414 return gResourceCache; | 470 return gResourceCache; |
415 } | 471 } |
416 | 472 |
| 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 |
417 size_t SkResourceCache::GetTotalBytesUsed() { | 502 size_t SkResourceCache::GetTotalBytesUsed() { |
418 SkAutoMutexAcquire am(gMutex); | 503 SkAutoMutexAcquire am(gMutex); |
419 return get_cache()->getTotalBytesUsed(); | 504 return get_cache()->getTotalBytesUsed(); |
420 } | 505 } |
421 | 506 |
422 size_t SkResourceCache::GetTotalByteLimit() { | 507 size_t SkResourceCache::GetTotalByteLimit() { |
423 SkAutoMutexAcquire am(gMutex); | 508 SkAutoMutexAcquire am(gMutex); |
424 return get_cache()->getTotalByteLimit(); | 509 return get_cache()->getTotalByteLimit(); |
425 } | 510 } |
426 | 511 |
(...skipping 20 matching lines...) Expand all Loading... |
447 size_t SkResourceCache::GetSingleAllocationByteLimit() { | 532 size_t SkResourceCache::GetSingleAllocationByteLimit() { |
448 SkAutoMutexAcquire am(gMutex); | 533 SkAutoMutexAcquire am(gMutex); |
449 return get_cache()->getSingleAllocationByteLimit(); | 534 return get_cache()->getSingleAllocationByteLimit(); |
450 } | 535 } |
451 | 536 |
452 void SkResourceCache::PurgeAll() { | 537 void SkResourceCache::PurgeAll() { |
453 SkAutoMutexAcquire am(gMutex); | 538 SkAutoMutexAcquire am(gMutex); |
454 return get_cache()->purgeAll(); | 539 return get_cache()->purgeAll(); |
455 } | 540 } |
456 | 541 |
457 bool SkResourceCache::Find(const Key& key, VisitorProc visitor, void* context) { | 542 const SkResourceCache::Rec* SkResourceCache::FindAndLock(const Key& key) { |
458 SkAutoMutexAcquire am(gMutex); | 543 SkAutoMutexAcquire am(gMutex); |
459 return get_cache()->find(key, visitor, context); | 544 return get_cache()->findAndLock(key); |
| 545 } |
| 546 |
| 547 const SkResourceCache::Rec* SkResourceCache::AddAndLock(Rec* rec) { |
| 548 SkAutoMutexAcquire am(gMutex); |
| 549 return get_cache()->addAndLock(rec); |
460 } | 550 } |
461 | 551 |
462 void SkResourceCache::Add(Rec* rec) { | 552 void SkResourceCache::Add(Rec* rec) { |
463 SkAutoMutexAcquire am(gMutex); | 553 SkAutoMutexAcquire am(gMutex); |
464 get_cache()->add(rec); | 554 get_cache()->add(rec); |
465 } | 555 } |
466 | 556 |
467 /////////////////////////////////////////////////////////////////////////////// | 557 /////////////////////////////////////////////////////////////////////////////// |
468 | 558 |
469 #include "SkGraphics.h" | 559 #include "SkGraphics.h" |
(...skipping 15 matching lines...) Expand all Loading... |
485 } | 575 } |
486 | 576 |
487 size_t SkGraphics::SetResourceCacheSingleAllocationByteLimit(size_t newLimit) { | 577 size_t SkGraphics::SetResourceCacheSingleAllocationByteLimit(size_t newLimit) { |
488 return SkResourceCache::SetSingleAllocationByteLimit(newLimit); | 578 return SkResourceCache::SetSingleAllocationByteLimit(newLimit); |
489 } | 579 } |
490 | 580 |
491 void SkGraphics::PurgeResourceCache() { | 581 void SkGraphics::PurgeResourceCache() { |
492 return SkResourceCache::PurgeAll(); | 582 return SkResourceCache::PurgeAll(); |
493 } | 583 } |
494 | 584 |
OLD | NEW |