| 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 |