Allow font-cache to use thread_local_storage for a private cache

Review URL: https://codereview.appspot.com/6200051

git-svn-id: http://skia.googlecode.com/svn/trunk@3986 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2012-05-17 13:38:03 +00:00
parent ff0da4ff48
commit 6172d67d1c
2 changed files with 73 additions and 7 deletions

View File

@ -65,6 +65,29 @@ public:
*/ */
static void SetFlags(const char* flags); 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: private:
/** This is automatically called by SkGraphics::Init(), and must be /** This is automatically called by SkGraphics::Init(), and must be
implemented by the host OS. This allows the host OS to register a callback implemented by the host OS. This allows the host OS to register a callback

View File

@ -11,6 +11,7 @@
#include "SkGraphics.h" #include "SkGraphics.h"
#include "SkPaint.h" #include "SkPaint.h"
#include "SkTemplates.h" #include "SkTemplates.h"
#include "SkTLS.h"
//#define SPEW_PURGE_STATUS //#define SPEW_PURGE_STATUS
//#define USE_CACHE_HASH //#define USE_CACHE_HASH
@ -414,17 +415,27 @@ void SkGlyphCache::invokeAndRemoveAuxProcs() {
class SkGlyphCache_Globals { class SkGlyphCache_Globals {
public: public:
SkGlyphCache_Globals() { enum UseMutex {
kNo_UseMutex, // thread-local cache
kYes_UseMutex, // shared cache
};
SkGlyphCache_Globals(UseMutex um) {
fHead = NULL; fHead = NULL;
fTotalMemoryUsed = 0; fTotalMemoryUsed = 0;
fFontCacheLimit = SK_DEFAULT_FONT_CACHE_LIMIT; fFontCacheLimit = SK_DEFAULT_FONT_CACHE_LIMIT;
fMutex = (kYes_UseMutex == um) ? SkNEW(SkMutex) : NULL;
#ifdef USE_CACHE_HASH #ifdef USE_CACHE_HASH
sk_bzero(fHash, sizeof(fHash)); sk_bzero(fHash, sizeof(fHash));
#endif #endif
} }
SkMutex fMutex; ~SkGlyphCache_Globals() {
SkDELETE(fMutex);
}
SkMutex* fMutex;
SkGlyphCache* fHead; SkGlyphCache* fHead;
size_t fTotalMemoryUsed; size_t fTotalMemoryUsed;
#ifdef USE_CACHE_HASH #ifdef USE_CACHE_HASH
@ -440,8 +451,27 @@ public:
size_t getFontCacheLimit() const { return fFontCacheLimit; } size_t getFontCacheLimit() const { return fFontCacheLimit; }
size_t setFontCacheLimit(size_t limit); 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: private:
size_t fFontCacheLimit; 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) { size_t SkGlyphCache_Globals::setFontCacheLimit(size_t newLimit) {
@ -455,9 +485,8 @@ size_t SkGlyphCache_Globals::setFontCacheLimit(size_t newLimit) {
size_t currUsed = fTotalMemoryUsed; size_t currUsed = fTotalMemoryUsed;
if (currUsed > newLimit) { if (currUsed > newLimit) {
fMutex.acquire(); SkAutoMutexAcquire ac(fMutex);
SkGlyphCache::InternalFreeCache(this, currUsed - newLimit); SkGlyphCache::InternalFreeCache(this, currUsed - newLimit);
fMutex.release();
} }
return prevLimit; return prevLimit;
} }
@ -465,14 +494,15 @@ size_t SkGlyphCache_Globals::setFontCacheLimit(size_t newLimit) {
// Returns the shared globals // Returns the shared globals
static SkGlyphCache_Globals& getSharedGlobals() { static SkGlyphCache_Globals& getSharedGlobals() {
// we leak this, so we don't incur any shutdown cost of the destructor // 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; return *gGlobals;
} }
// Returns the TLS globals (if set), or the shared globals // Returns the TLS globals (if set), or the shared globals
static SkGlyphCache_Globals& getGlobals() { static SkGlyphCache_Globals& getGlobals() {
// TODO: Check TLS for local globals... SkGlyphCache_Globals* tls = SkGlyphCache_Globals::FindTLS();
return getSharedGlobals(); return tls ? *tls : getSharedGlobals();
} }
void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*), void SkGlyphCache::VisitAllCaches(bool (*proc)(SkGlyphCache*, void*),
@ -698,3 +728,16 @@ void SkGraphics::PurgeFontCache() {
SkTypefaceCache::PurgeAll(); 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);
}
}