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

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: address more comments 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
« no previous file with comments | « no previous file | src/core/SkGlyphCache_Globals.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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& get_globals() {
33 return *globals.get(); 33 return *globals.get();
34 } 34 }
35 35
36 // Returns the TLS globals (if set), or the shared globals
37 static SkGlyphCache_Globals& getGlobals() {
38 SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
39 return tls ? *tls : getSharedGlobals();
40 }
41
42 /////////////////////////////////////////////////////////////////////////////// 36 ///////////////////////////////////////////////////////////////////////////////
43 37
44 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 38 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
45 #define RecordHashSuccess() fHashHitCount += 1 39 #define RecordHashSuccess() fHashHitCount += 1
46 #define RecordHashCollisionIf(pred) do { if (pred) fHashMissCount += 1; } while (0) 40 #define RecordHashCollisionIf(pred) do { if (pred) fHashMissCount += 1; } while (0)
47 #else 41 #else
48 #define RecordHashSuccess() (void)0 42 #define RecordHashSuccess() (void)0
49 #define RecordHashCollisionIf(pred) (void)0 43 #define RecordHashCollisionIf(pred) (void)0
50 #endif 44 #endif
51 #define RecordHashCollision() RecordHashCollisionIf(true) 45 #define RecordHashCollision() RecordHashCollisionIf(true)
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 rec->fProc(rec->fData); 405 rec->fProc(rec->fData);
412 AuxProcRec* next = rec->fNext; 406 AuxProcRec* next = rec->fNext;
413 SkDELETE(rec); 407 SkDELETE(rec);
414 rec = next; 408 rec = next;
415 } 409 }
416 } 410 }
417 411
418 /////////////////////////////////////////////////////////////////////////////// 412 ///////////////////////////////////////////////////////////////////////////////
419 /////////////////////////////////////////////////////////////////////////////// 413 ///////////////////////////////////////////////////////////////////////////////
420 414
415
416 class AutoAcquire {
417 public:
418 AutoAcquire(SkSpinlock& lock) : fLock(lock) { fLock.acquire(); }
419 ~AutoAcquire() { fLock.release(); }
420 private:
421 SkSpinlock& fLock;
422 };
423
421 size_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) { 424 size_t SkGlyphCache_Globals::setCacheSizeLimit(size_t newLimit) {
422 static const size_t minLimit = 256 * 1024; 425 static const size_t minLimit = 256 * 1024;
423 if (newLimit < minLimit) { 426 if (newLimit < minLimit) {
424 newLimit = minLimit; 427 newLimit = minLimit;
425 } 428 }
426 429
427 SkAutoMutexAcquire ac(fMutex); 430 AutoAcquire ac(fLock);
428 431
429 size_t prevLimit = fCacheSizeLimit; 432 size_t prevLimit = fCacheSizeLimit;
430 fCacheSizeLimit = newLimit; 433 fCacheSizeLimit = newLimit;
431 this->internalPurge(); 434 this->internalPurge();
432 return prevLimit; 435 return prevLimit;
433 } 436 }
434 437
435 int SkGlyphCache_Globals::setCacheCountLimit(int newCount) { 438 int SkGlyphCache_Globals::setCacheCountLimit(int newCount) {
436 if (newCount < 0) { 439 if (newCount < 0) {
437 newCount = 0; 440 newCount = 0;
438 } 441 }
439 442
440 SkAutoMutexAcquire ac(fMutex); 443 AutoAcquire ac(fLock);
441 444
442 int prevCount = fCacheCountLimit; 445 int prevCount = fCacheCountLimit;
443 fCacheCountLimit = newCount; 446 fCacheCountLimit = newCount;
444 this->internalPurge(); 447 this->internalPurge();
445 return prevCount; 448 return prevCount;
446 } 449 }
447 450
448 void SkGlyphCache_Globals::purgeAll() { 451 void SkGlyphCache_Globals::purgeAll() {
449 SkAutoMutexAcquire ac(fMutex); 452 AutoAcquire ac(fLock);
450 this->internalPurge(fTotalMemoryUsed); 453 this->internalPurge(fTotalMemoryUsed);
451 } 454 }
452 455
453 /* This guy calls the visitor from within the mutext lock, so the visitor 456 /* This guy calls the visitor from within the mutext lock, so the visitor
454 cannot: 457 cannot:
455 - take too much time 458 - take too much time
456 - try to acquire the mutext again 459 - try to acquire the mutext again
457 - call a fontscaler (which might call into the cache) 460 - call a fontscaler (which might call into the cache)
458 */ 461 */
459 SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface, 462 SkGlyphCache* SkGlyphCache::VisitCache(SkTypeface* typeface,
460 const SkDescriptor* desc, 463 const SkDescriptor* desc,
461 bool (*proc)(const SkGlyphCache*, void*), 464 bool (*proc)(const SkGlyphCache*, void*),
462 void* context) { 465 void* context) {
463 if (!typeface) { 466 if (!typeface) {
464 typeface = SkTypeface::GetDefaultTypeface(); 467 typeface = SkTypeface::GetDefaultTypeface();
465 } 468 }
466 SkASSERT(desc); 469 SkASSERT(desc);
467 470
468 SkGlyphCache_Globals& globals = getGlobals(); 471 SkGlyphCache_Globals& globals = get_globals();
469 SkAutoMutexAcquire ac(globals.fMutex);
470 SkGlyphCache* cache; 472 SkGlyphCache* cache;
471 bool insideMutex = true;
472 473
473 globals.validate(); 474 {
475 AutoAcquire ac(globals.fLock);
474 476
475 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) { 477 globals.validate();
476 if (cache->fDesc->equals(*desc)) { 478
477 globals.internalDetachCache(cache); 479 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fN ext) {
478 goto FOUND_IT; 480 if (cache->fDesc->equals(*desc)) {
481 globals.internalDetachCache(cache);
482 if (!proc(cache, context)) {
483 globals.internalAttachCacheToHead(cache);
484 cache = NULL;
485 }
486 return cache;
487 }
479 } 488 }
480 } 489 }
481 490
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. 491 // 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 492 // If not, we may have exhausted OS/font resources, so try purging the
490 // cache once and try again. 493 // cache once and try again.
491 { 494 {
492 // pass true the first time, to notice if the scalercontext failed, 495 // pass true the first time, to notice if the scalercontext failed,
493 // so we can try the purge. 496 // so we can try the purge.
494 SkScalerContext* ctx = typeface->createScalerContext(desc, true); 497 SkScalerContext* ctx = typeface->createScalerContext(desc, true);
495 if (!ctx) { 498 if (!ctx) {
496 getSharedGlobals().purgeAll(); 499 get_globals().purgeAll();
497 ctx = typeface->createScalerContext(desc, false); 500 ctx = typeface->createScalerContext(desc, false);
498 SkASSERT(ctx); 501 SkASSERT(ctx);
499 } 502 }
500 cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx)); 503 cache = SkNEW_ARGS(SkGlyphCache, (typeface, desc, ctx));
501 } 504 }
502 505
503 FOUND_IT:
504
505 AutoValidate av(cache); 506 AutoValidate av(cache);
506 507
507 if (!proc(cache, context)) { // need to reattach 508 if (!proc(cache, context)) { // need to reattach
508 if (insideMutex) { 509 globals.attachCacheToHead(cache);
509 globals.internalAttachCacheToHead(cache);
510 } else {
511 globals.attachCacheToHead(cache);
512 }
513 cache = NULL; 510 cache = NULL;
514 } 511 }
515 return cache; 512 return cache;
516 } 513 }
517 514
518 void SkGlyphCache::AttachCache(SkGlyphCache* cache) { 515 void SkGlyphCache::AttachCache(SkGlyphCache* cache) {
519 SkASSERT(cache); 516 SkASSERT(cache);
520 SkASSERT(cache->fNext == NULL); 517 SkASSERT(cache->fNext == NULL);
521 518
522 getGlobals().attachCacheToHead(cache); 519 get_globals().attachCacheToHead(cache);
523 } 520 }
524 521
525 void SkGlyphCache::Dump() { 522 void SkGlyphCache::Dump() {
526 SkGlyphCache_Globals& globals = getGlobals(); 523 SkGlyphCache_Globals& globals = get_globals();
527 SkAutoMutexAcquire ac(globals.fMutex); 524 AutoAcquire ac(globals.fLock);
528 SkGlyphCache* cache; 525 SkGlyphCache* cache;
529 526
530 globals.validate(); 527 globals.validate();
531 528
532 SkDebugf("SkGlyphCache strikes:%d memory:%d\n", 529 SkDebugf("SkGlyphCache strikes:%d memory:%d\n",
533 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed()); 530 globals.getCacheCountUsed(), (int)globals.getTotalMemoryUsed());
534 531
535 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 532 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
536 int hitCount = 0; 533 int hitCount = 0;
537 int missCount = 0; 534 int missCount = 0;
538 #endif 535 #endif
539 536
540 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) { 537 for (cache = globals.internalGetHead(); cache != NULL; cache = cache->fNext) {
541 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 538 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
542 hitCount += cache->fHashHitCount; 539 hitCount += cache->fHashHitCount;
543 missCount += cache->fHashMissCount; 540 missCount += cache->fHashMissCount;
544 #endif 541 #endif
545 cache->dump(); 542 cache->dump();
546 } 543 }
547 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS 544 #ifdef SK_GLYPHCACHE_TRACK_HASH_STATS
548 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount)); 545 SkDebugf("Hash hit percent:%2d\n", 100 * hitCount / (hitCount + missCount));
549 #endif 546 #endif
550 } 547 }
551 548
552 /////////////////////////////////////////////////////////////////////////////// 549 ///////////////////////////////////////////////////////////////////////////////
553 550
554 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) { 551 void SkGlyphCache_Globals::attachCacheToHead(SkGlyphCache* cache) {
555 SkAutoMutexAcquire ac(fMutex); 552 AutoAcquire ac(fLock);
556 553
557 this->validate(); 554 this->validate();
558 cache->validate(); 555 cache->validate();
559 556
560 this->internalAttachCacheToHead(cache); 557 this->internalAttachCacheToHead(cache);
561 this->internalPurge(); 558 this->internalPurge();
562 } 559 }
563 560
564 SkGlyphCache* SkGlyphCache_Globals::internalGetTail() const { 561 SkGlyphCache* SkGlyphCache_Globals::internalGetTail() const {
565 SkGlyphCache* cache = fHead; 562 SkGlyphCache* cache = fHead;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
674 size_t computedBytes = 0; 671 size_t computedBytes = 0;
675 int computedCount = 0; 672 int computedCount = 0;
676 673
677 const SkGlyphCache* head = fHead; 674 const SkGlyphCache* head = fHead;
678 while (head != NULL) { 675 while (head != NULL) {
679 computedBytes += head->fMemoryUsed; 676 computedBytes += head->fMemoryUsed;
680 computedCount += 1; 677 computedCount += 1;
681 head = head->fNext; 678 head = head->fNext;
682 } 679 }
683 680
684 SkASSERT(fTotalMemoryUsed == computedBytes); 681 SkASSERTF(fCacheCount == computedCount, "fCacheCount: %d, computedCount: %d" , fCacheCount,
685 SkASSERT(fCacheCount == computedCount); 682 computedCount);
683 SkASSERTF(fTotalMemoryUsed == computedBytes, "fTotalMemoryUsed: %d, computed Bytes: %d",
684 fTotalMemoryUsed, computedBytes);
686 } 685 }
687 686
688 #endif 687 #endif
689 688
690 /////////////////////////////////////////////////////////////////////////////// 689 ///////////////////////////////////////////////////////////////////////////////
691 /////////////////////////////////////////////////////////////////////////////// 690 ///////////////////////////////////////////////////////////////////////////////
692 691
693 #include "SkTypefaceCache.h" 692 #include "SkTypefaceCache.h"
694 693
695 size_t SkGraphics::GetFontCacheLimit() { 694 size_t SkGraphics::GetFontCacheLimit() {
696 return getSharedGlobals().getCacheSizeLimit(); 695 return get_globals().getCacheSizeLimit();
697 } 696 }
698 697
699 size_t SkGraphics::SetFontCacheLimit(size_t bytes) { 698 size_t SkGraphics::SetFontCacheLimit(size_t bytes) {
700 return getSharedGlobals().setCacheSizeLimit(bytes); 699 return get_globals().setCacheSizeLimit(bytes);
701 } 700 }
702 701
703 size_t SkGraphics::GetFontCacheUsed() { 702 size_t SkGraphics::GetFontCacheUsed() {
704 return getSharedGlobals().getTotalMemoryUsed(); 703 return get_globals().getTotalMemoryUsed();
705 } 704 }
706 705
707 int SkGraphics::GetFontCacheCountLimit() { 706 int SkGraphics::GetFontCacheCountLimit() {
708 return getSharedGlobals().getCacheCountLimit(); 707 return get_globals().getCacheCountLimit();
709 } 708 }
710 709
711 int SkGraphics::SetFontCacheCountLimit(int count) { 710 int SkGraphics::SetFontCacheCountLimit(int count) {
712 return getSharedGlobals().setCacheCountLimit(count); 711 return get_globals().setCacheCountLimit(count);
713 } 712 }
714 713
715 int SkGraphics::GetFontCacheCountUsed() { 714 int SkGraphics::GetFontCacheCountUsed() {
716 return getSharedGlobals().getCacheCountUsed(); 715 return get_globals().getCacheCountUsed();
717 } 716 }
718 717
719 void SkGraphics::PurgeFontCache() { 718 void SkGraphics::PurgeFontCache() {
720 getSharedGlobals().purgeAll(); 719 get_globals().purgeAll();
721 SkTypefaceCache::PurgeAll(); 720 SkTypefaceCache::PurgeAll();
722 } 721 }
723 722
724 size_t SkGraphics::GetTLSFontCacheLimit() { 723 // TODO(herb): clean up TLS apis.
725 const SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS(); 724 size_t SkGraphics::GetTLSFontCacheLimit() { return 0; }
726 return tls ? tls->getCacheSizeLimit() : 0; 725 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) { }
727 }
728
729 void SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
730 if (0 == bytes) {
731 SkGlyphCache_Globals::DeleteTLS();
732 } else {
733 SkGlyphCache_Globals::GetTLS().setCacheSizeLimit(bytes);
734 }
735 }
OLDNEW
« no previous file with comments | « no previous file | src/core/SkGlyphCache_Globals.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698