Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: src/core/SkGlyphCache.cpp

Issue 1210143004: SkGlyphCache_Globals: SkMutex -> SkSpinlock (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: remove tls, move autolock and other Created 5 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2006 The Android Open Source Project 2 * Copyright 2006 The Android Open Source Project
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 "SkGlyphCache.h" 8 #include "SkGlyphCache.h"
9 #include "SkGlyphCache_Globals.h" 9 #include "SkGlyphCache_Globals.h"
10 #include "SkGraphics.h" 10 #include "SkGraphics.h"
11 #include "SkLazyPtr.h" 11 #include "SkLazyPtr.h"
12 #include "SkMutex.h" 12 #include "SkMutex.h"
13 #include "SkPaint.h" 13 #include "SkPaint.h"
14 #include "SkPath.h" 14 #include "SkPath.h"
15 #include "SkTLS.h" 15 #include "SkTLS.h"
16 #include "SkTemplates.h" 16 #include "SkTemplates.h"
17 #include "SkTypeface.h" 17 #include "SkTypeface.h"
18 18
19 //#define SPEW_PURGE_STATUS 19 //#define SPEW_PURGE_STATUS
20 20
21 namespace { 21 namespace {
22 22
23 SkGlyphCache_Globals* create_globals() { 23 SkGlyphCache_Globals* create_globals() {
24 return SkNEW_ARGS(SkGlyphCache_Globals, (SkGlyphCache_Globals::kYes_UseMutex )); 24 return SkNEW(SkGlyphCache_Globals);
25 } 25 }
26 26
27 } // namespace 27 } // namespace
28 28
29 SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals); 29 SK_DECLARE_STATIC_LAZY_PTR(SkGlyphCache_Globals, globals, create_globals);
30 30
31 // Returns the shared globals 31 // Returns the shared globals
32 static SkGlyphCache_Globals& getSharedGlobals() { 32 static SkGlyphCache_Globals& getSharedGlobals() {
33 return *globals.get(); 33 return *globals.get();
34 } 34 }
35 35
36 // Returns the TLS globals (if set), or the shared globals 36 // Returns the TLS globals (if set), or the shared globals
37 static SkGlyphCache_Globals& getGlobals() { 37 static SkGlyphCache_Globals& getGlobals() {
mtklein_C 2015/07/09 16:46:22 seems like we can merge getGlobals() and getShared
herb_g 2015/07/09 18:21:15 Done.
38 SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); 38 return getSharedGlobals();
39 return tls ? *tls : getSharedGlobals();
40 } 39 }
41 40
42 /////////////////////////////////////////////////////////////////////////////// 41 ///////////////////////////////////////////////////////////////////////////////
43 42
44 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 43 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
45 #define RecordHashSuccess() fHashHitCount += 1 44 #define RecordHashSuccess() fHashHitCount += 1
46 #define RecordHashCollisionIf(pred) do { if (pred) fHashMissCount += 1; } while (0) 45 #define RecordHashCollisionIf(pred) do { if (pred) fHashMissCount += 1; } while (0)
47 #else 46 #else
48 #define RecordHashSuccess() (void)0 47 #define RecordHashSuccess() (void)0
49 #define RecordHashCollisionIf(pred) (void)0 48 #define RecordHashCollisionIf(pred) (void)0
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 rec->fProc(rec->fData); 410 rec->fProc(rec->fData);
412 AuxProcRec* next = rec->fNext; 411 AuxProcRec* next = rec->fNext;
413 SkDELETE(rec); 412 SkDELETE(rec);
414 rec = next; 413 rec = next;
415 } 414 }
416 } 415 }
417 416
418 /////////////////////////////////////////////////////////////////////////////// 417 ///////////////////////////////////////////////////////////////////////////////
419 /////////////////////////////////////////////////////////////////////////////// 418 ///////////////////////////////////////////////////////////////////////////////
420 419
420
421 class AutoAcquire {
422 public:
423 AutoAcquire(SkSpinlock& lock) : fLock(lock) { fLock.acquire(); }
424 ~AutoAcquire() { fLock.release(); }
425 private:
426 SkSpinlock& fLock;
427 };
428
421 size_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) { 429 size_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) {
422 static const size_t minLimit = 256 * 1024; 430 static const size_t minLimit = 256 * 1024;
423 if (newLimit < minLimit) { 431 if (newLimit < minLimit) {
424 newLimit = minLimit; 432 newLimit = minLimit;
425 } 433 }
426 434
427 SkAutoMutexAcquire ac(fMutex); 435 AutoAcquire ac(fLock);
428 436
429 size_t prevLimit = fCacheSizeLimit; 437 size_t prevLimit = fCacheSizeLimit;
430 fCacheSizeLimit = newLimit; 438 fCacheSizeLimit = newLimit;
431 this->internalPurge(); 439 this->internalPurge();
432 return prevLimit; 440 return prevLimit;
433 } 441 }
434 442
435 int SkGlyphCache_Globals::setCacheCountLimit(int newCount) { 443 int SkGlyphCache_Globals::setCacheCountLimit(int newCount) {
436 if (newCount < 0) { 444 if (newCount < 0) {
437 newCount = 0; 445 newCount = 0;
438 } 446 }
439 447
440 SkAutoMutexAcquire ac(fMutex); 448 AutoAcquire ac(fLock);
441 449
442 int prevCount = fCacheCountLimit; 450 int prevCount = fCacheCountLimit;
443 fCacheCountLimit = newCount; 451 fCacheCountLimit = newCount;
444 this->internalPurge(); 452 this->internalPurge();
445 return prevCount; 453 return prevCount;
446 } 454 }
447 455
448 void SkGlyphCache_Globals::purgeAll() { 456 void SkGlyphCache_Globals::purgeAll() {
449 SkAutoMutexAcquire ac(fMutex); 457 AutoAcquire ac(fLock);
450 this->internalPurge(fTotalMemoryUsed); 458 this->internalPurge(fTotalMemoryUsed);
451 } 459 }
452 460
453 /* This guy calls the visitor from within the mutext lock, so the visitor 461 /* This guy calls the visitor from within the mutext lock, so the visitor
454 cannot: 462 cannot:
455 - take too much time 463 - take too much time
456 - try to acquire the mutext again 464 - try to acquire the mutext again
457 - call a fontscaler (which might call into the cache) 465 - call a fontscaler (which might call into the cache)
458 */ 466 */
459 SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface, 467 SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface,
460 const SkDescriptor* desc, 468 const SkDescriptor* desc,
461 bool (*proc)(const SkGlyphCache*, void*), 469 bool (*proc)(const SkGlyphCache*, void*),
462 void* context) { 470 void* context) {
463 if (!typeface) { 471 if (!typeface) {
464 typeface = SkTypeface::GetDefaultTypeface(); 472 typeface = SkTypeface::GetDefaultTypeface();
465 } 473 }
466 SkASSERT(desc); 474 SkASSERT(desc);
467 475
468 SkGlyphCache_Globals& globals = getGlobals(); 476 SkGlyphCache_Globals& globals = getGlobals();
469 SkAutoMutexAcquire ac(globals.fMutex);
470 SkGlyphCache* cache; 477 SkGlyphCache* cache;
471 bool insideMutex = true;
472 478
473 globals.validate(); 479 {
480 AutoAcquire ac(globals.fLock);
474 481
475 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) { 482 globals.validate();
476 if (cache->fDesc->equals(*desc)) { 483
477 globals.internalDetachCache(cache); 484 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fN ext) {
478 goto FOUND_IT; 485 if (cache->fDesc->equals(*desc)) {
486 globals.internalDetachCache(cache);
487 if (!proc(cache, context)) {
488 globals.internalAttachCacheToHead(cache);
mtklein_C 2015/07/09 16:46:22 Thanks, I find this code a lot easier to follow th
herb_g 2015/07/09 18:21:15 Acknowledged.
489 cache = NULL;
490 }
491 return cache;
492 }
479 } 493 }
480 } 494 }
481 495
482 /* Release the mutex now, before we create a new entry (which might have
483 side-effects like trying to access the cache/mutex (yikes!)
484 */
485 ac.release(); // release the mutex now
486 insideMutex = false; // can't use globals anymore
487
488 // Check if we can create a scaler-context before creating the glyphcache. 496 // Check if we can create a scaler-context before creating the glyphcache.
489 // If not, we may have exhausted OS/font resources, so try purging the 497 // If not, we may have exhausted OS/font resources, so try purging the
490 // cache once and try again. 498 // cache once and try again.
491 { 499 {
492 // pass true the first time, to notice if the scalercontext failed, 500 // pass true the first time, to notice if the scalercontext failed,
493 // so we can try the purge. 501 // so we can try the purge.
494 SkScalerContext* ctx = typeface->createScalerContext(desc, true); 502 SkScalerContext* ctx = typeface->createScalerContext(desc, true);
495 if (!ctx) { 503 if (!ctx) {
496 getSharedGlobals().purgeAll(); 504 getSharedGlobals().purgeAll();
497 ctx = typeface->createScalerContext(desc, false); 505 ctx = typeface->createScalerContext(desc, false);
498 SkASSERT(ctx); 506 SkASSERT(ctx);
499 } 507 }
500 cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx)); 508 cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx));
501 } 509 }
502 510
503 FOUND_IT:
504
505 AutoValidate av(cache); 511 AutoValidate av(cache);
506 512
507 if (!proc(cache, context)) { // need to reattach 513 if (!proc(cache, context)) { // need to reattach
508 if (insideMutex) { 514 globals.attachCacheToHead(cache);
509 globals.internalAttachCacheToHead(cache);
510 } else {
511 globals.attachCacheToHead(cache);
512 }
513 cache = NULL; 515 cache = NULL;
514 } 516 }
515 return cache; 517 return cache;
516 } 518 }
517 519
518 void SkGlyphCache::AttachCache(SkGlyphCache* cache) { 520 void SkGlyphCache::AttachCache(SkGlyphCache* cache) {
519 SkASSERT(cache); 521 SkASSERT(cache);
520 SkASSERT(cache->fNext == NULL); 522 SkASSERT(cache->fNext == NULL);
521 523
522 getGlobals().attachCacheToHead(cache); 524 getGlobals().attachCacheToHead(cache);
523 } 525 }
524 526
525 void SkGlyphCache::Dump() { 527 void SkGlyphCache::Dump() {
526 SkGlyphCache_Globals& globals = getGlobals(); 528 SkGlyphCache_Globals& globals = getGlobals();
527 SkAutoMutexAcquire ac(globals.fMutex); 529 AutoAcquire ac(globals.fLock);
528 SkGlyphCache* cache; 530 SkGlyphCache* cache;
529 531
530 globals.validate(); 532 globals.validate();
531 533
532 SkDebugf("SkGlyphCache strikes:%d memory:%d\n", 534 SkDebugf("SkGlyphCache strikes:%d memory:%d\n",
533 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed()); 535 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed());
534 536
535 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 537 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
536 int hitCount = 0; 538 int hitCount = 0;
537 int missCount = 0; 539 int missCount = 0;
538 #endif 540 #endif
539 541
540 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) { 542 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) {
541 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 543 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
542 hitCount += cache->fHashHitCount; 544 hitCount += cache->fHashHitCount;
543 missCount += cache->fHashMissCount; 545 missCount += cache->fHashMissCount;
544 #endif 546 #endif
545 cache->dump(); 547 cache->dump();
546 } 548 }
547 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 549 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
548 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount)); 550 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount));
549 #endif 551 #endif
550 } 552 }
551 553
552 /////////////////////////////////////////////////////////////////////////////// 554 ///////////////////////////////////////////////////////////////////////////////
553 555
554 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { 556 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) {
555 SkAutoMutexAcquire ac(fMutex); 557 AutoAcquire ac(fLock);
556 558
557 this->validate(); 559 this->validate();
558 cache->validate(); 560 cache->validate();
559 561
560 this->internalAttachCacheToHead(cache); 562 this->internalAttachCacheToHead(cache);
561 this->internalPurge(); 563 this->internalPurge();
562 } 564 }
563 565
564 SkGlyphCache* SkGlyphCache_Globals::internalGetTail() const { 566 SkGlyphCache* SkGlyphCache_Globals::internalGetTail() const {
565 SkGlyphCache* cache = fHead; 567 SkGlyphCache* cache = fHead;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 size_t computedBytes = 0; 676 size_t computedBytes = 0;
675 int computedCount = 0; 677 int computedCount = 0;
676 678
677 const SkGlyphCache* head = fHead; 679 const SkGlyphCache* head = fHead;
678 while (head != NULL) { 680 while (head != NULL) {
679 computedBytes += head->fMemoryUsed; 681 computedBytes += head->fMemoryUsed;
680 computedCount += 1; 682 computedCount += 1;
681 head = head->fNext; 683 head = head->fNext;
682 } 684 }
683 685
684 SkASSERT(fTotalMemoryUsed == computedBytes); 686 SkASSERTF(fCacheCount == computedCount, "fCacheCount: %d, computedCount: %d" , fCacheCount,
685 SkASSERT(fCacheCount == computedCount); 687 computedCount);
688 SkASSERTF(fTotalMemoryUsed == computedBytes, "fTotalMemoryUsed: %d, computed Bytes: %d",
689 fTotalMemoryUsed, computedBytes);
686 } 690 }
687 691
688 #endif 692 #endif
689 693
690 /////////////////////////////////////////////////////////////////////////////// 694 ///////////////////////////////////////////////////////////////////////////////
691 /////////////////////////////////////////////////////////////////////////////// 695 ///////////////////////////////////////////////////////////////////////////////
692 696
693 #include "SkTypefaceCache.h" 697 #include "SkTypefaceCache.h"
694 698
695 size_t SkGraphics::GetFontCacheLimit() { 699 size_t SkGraphics::GetFontCacheLimit() {
(...skipping 18 matching lines...) Expand all
714 718
715 int SkGraphics::GetFontCacheCountUsed() { 719 int SkGraphics::GetFontCacheCountUsed() {
716 return getSharedGlobals().getCacheCountUsed(); 720 return getSharedGlobals().getCacheCountUsed();
717 } 721 }
718 722
719 void SkGraphics::PurgeFontCache() { 723 void SkGraphics::PurgeFontCache() {
720 getSharedGlobals().purgeAll(); 724 getSharedGlobals().purgeAll();
721 SkTypefaceCache::PurgeAll(); 725 SkTypefaceCache::PurgeAll();
722 } 726 }
723 727
724 size_t SkGraphics::GetTLSFontCacheLimit() { 728 size_t SkGraphics::GetTLSFontCacheLimit() {
mtklein_C 2015/07/09 16:46:22 TODO(mtklein): clean up TLS apis ?
herb_g 2015/07/09 18:21:15 Done.
725 const SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); 729 return 0;
726 return tls ? tls->getCacheSizeLimit() : 0;
727 } 730 }
728 731
729 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { 732 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
730 if (0 == bytes) {
731 SkGlyphCache_Globals::DeleteTLS();
732 } else {
733 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes);
734 }
735 } 733 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698