Allow font-cache to use thread_local_storage for a private cache
authorreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 17 May 2012 13:38:03 +0000 (13:38 +0000)
committerreed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Thu, 17 May 2012 13:38:03 +0000 (13:38 +0000)
Review URL: https://codereview.appspot.com/6200051

git-svn-id: http://skia.googlecode.com/svn/trunk@3986 2bbb7eff-a529-9590-31e7-b0007b416f81

include/core/SkGraphics.h
src/core/SkGlyphCache.cpp

index 9e78dde..3cfd70f 100644 (file)
@@ -65,6 +65,29 @@ public:
      */
     static void SetFlags(const char* flags);
     
+    /**
+     *  Return the max number of bytes that should be used by the thread-local
+     *  font cache.
+     *  If the cache needs to allocate more, it will purge previous entries.
+     *  This max can be changed by calling SetFontCacheLimit().
+     *
+     *  If this thread has never called SetTLSFontCacheLimit, or has called it
+     *  with 0, then this thread is using the shared font cache. In that case,
+     *  this function will always return 0, and the caller may want to call
+     *  GetFontCacheLimit.
+     */
+    static size_t GetTLSFontCacheLimit();
+    
+    /**
+     *  Specify the max number of bytes that should be used by the thread-local
+     *  font cache. If this value is zero (the default), then this thread will
+     *  share the global font cache and its limit.
+     *
+     *  This function returns the previous setting, as if GetFontCacheLimit()
+     *  had be called before the new limit was set.
+     */
+    static size_t SetTLSFontCacheLimit(size_t bytes);
+    
 private:
     /** This is automatically called by SkGraphics::Init(), and must be
         implemented by the host OS. This allows the host OS to register a callback
index b020f04..76d8c21 100644 (file)
@@ -11,6 +11,7 @@
 #include "SkGraphics.h"
 #include "SkPaint.h"
 #include "SkTemplates.h"
+#include "SkTLS.h"
 
 //#define SPEW_PURGE_STATUS
 //#define USE_CACHE_HASH
@@ -414,17 +415,27 @@ void SkGlyphCache::invokeAndRemoveAuxProcs() {
 
 class SkGlyphCache_Globals {
 public:
-    SkGlyphCache_Globals() {
+    enum UseMutex {
+        kNo_UseMutex,  // thread-local cache
+        kYes_UseMutex, // shared cache
+    };
+
+    SkGlyphCache_Globals(UseMutex um) {
         fHead = NULL;
         fTotalMemoryUsed = 0;
         fFontCacheLimit = SK_DEFAULT_FONT_CACHE_LIMIT;
+        fMutex = (kYes_UseMutex == um) ? SkNEW(SkMutex) : NULL;
 
 #ifdef USE_CACHE_HASH
         sk_bzero(fHash, sizeof(fHash));
 #endif
     }
 
-    SkMutex         fMutex;
+    ~SkGlyphCache_Globals() {
+        SkDELETE(fMutex);
+    }
+    
+    SkMutex*        fMutex;
     SkGlyphCache*   fHead;
     size_t          fTotalMemoryUsed;
 #ifdef USE_CACHE_HASH
@@ -440,8 +451,27 @@ public:
     size_t  getFontCacheLimit() const { return fFontCacheLimit; }
     size_t  setFontCacheLimit(size_t limit);
 
+    // can return NULL
+    static SkGlyphCache_Globals* FindTLS() {
+        return (SkGlyphCache_Globals*)SkTLS::Find(CreateTLS);
+    }
+    
+    static SkGlyphCache_Globals& GetTLS() {
+        return *(SkGlyphCache_Globals*)SkTLS::Get(CreateTLS, DeleteTLS);
+    }
+
+    static void DeleteTLS() { SkTLS::Delete(CreateTLS); }
+
 private:
     size_t  fFontCacheLimit;
+
+    static void* CreateTLS() {
+        return SkNEW_ARGS(SkGlyphCache_Globals, (kNo_UseMutex));
+    }
+
+    static void DeleteTLS(void* ptr) {
+        SkDELETE((SkGlyphCache_Globals*)ptr);
+    }
 };
 
 size_t SkGlyphCache_Globals::setFontCacheLimit(size_t newLimit) {
@@ -455,9 +485,8 @@ size_t SkGlyphCache_Globals::setFontCacheLimit(size_t newLimit) {
     
     size_t currUsed = fTotalMemoryUsed;
     if (currUsed > newLimit) {
-        fMutex.acquire();
+        SkAutoMutexAcquire    ac(fMutex);
         SkGlyphCache::InternalFreeCache(this, currUsed - newLimit);
-        fMutex.release();
     }
     return prevLimit;
 }
@@ -465,14 +494,15 @@ size_t SkGlyphCache_Globals::setFontCacheLimit(size_t newLimit) {
 // Returns the shared globals
 static SkGlyphCache_Globals& getSharedGlobals() {
     // we leak this, so we don't incur any shutdown cost of the destructor
-    static SkGlyphCache_Globals* gGlobals = new SkGlyphCache_Globals;
+    static SkGlyphCache_Globals* gGlobals = SkNEW_ARGS(SkGlyphCache_Globals,
+                                       (SkGlyphCache_Globals::kYes_UseMutex));
     return *gGlobals;
 }
 
 // Returns the TLS globals (if set), or the shared globals
 static SkGlyphCache_Globals& getGlobals() {
-    // TODO: Check TLS for local globals...
-    return getSharedGlobals();
+    SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
+    return tls ? *tls : getSharedGlobals();
 }
 
 void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*),
@@ -698,3 +728,16 @@ void SkGraphics::PurgeFontCache() {
     SkTypefaceCache::PurgeAll();
 }
 
+size_t SkGraphics::GetTLSFontCacheLimit() {
+    const SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
+    return tls ? tls->getFontCacheLimit() : 0;
+}
+
+size_t SkGraphics::SetTLSFontCacheLimit(size_t bytes) {
+    if (0 == bytes) {
+        SkGlyphCache_Globals::DeleteTLS();
+    } else {
+        SkGlyphCache_Globals::GetTLS().setFontCacheLimit(bytes);
+    }
+}
+