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