add counting to Globals, and refactor some for clarity

BUG=

Review URL: https://codereview.chromium.org/24447003

git-svn-id: http://skia.googlecode.com/svn/trunk@11484 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/core/SkGlyphCache_Globals.h b/src/core/SkGlyphCache_Globals.h
new file mode 100644
index 0000000..20b0f29
--- /dev/null
+++ b/src/core/SkGlyphCache_Globals.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2010 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkGlyphCache_Globals_DEFINED
+#define SkGlyphCache_Globals_DEFINED
+
+#include "SkGlyphCache.h"
+#include "SkTLS.h"
+
+#ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT
+    #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT   256
+#endif
+
+#ifndef SK_DEFAULT_FONT_CACHE_LIMIT
+    #define SK_DEFAULT_FONT_CACHE_LIMIT     (2 * 1024 * 1024)
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+class SkMutex;
+
+class SkGlyphCache_Globals {
+public:
+    enum UseMutex {
+        kNo_UseMutex,  // thread-local cache
+        kYes_UseMutex  // shared cache
+    };
+    
+    SkGlyphCache_Globals(UseMutex um) {
+        fHead = NULL;
+        fTotalMemoryUsed = 0;
+        fCacheSizeLimit = SK_DEFAULT_FONT_CACHE_LIMIT;
+        fCacheCount = 0;
+        fCacheCountLimit = SK_DEFAULT_FONT_CACHE_COUNT_LIMIT;
+    
+        fMutex = (kYes_UseMutex == um) ? SkNEW(SkMutex) : NULL;
+    }
+    
+    ~SkGlyphCache_Globals() {
+        SkGlyphCache* cache = fHead;
+        while (cache) {
+            SkGlyphCache* next = cache->fNext;
+            SkDELETE(cache);
+            cache = next;
+        }
+        
+        SkDELETE(fMutex);
+    }
+    
+    SkMutex*        fMutex;
+
+    SkGlyphCache* internalGetHead() const { return fHead; }
+    SkGlyphCache* internalGetTail() const;
+
+    size_t getTotalMemoryUsed() const { return fTotalMemoryUsed; }
+    int getCacheCountUsed() const { return fCacheCount; }
+
+#ifdef SK_DEBUG
+    void validate() const;
+#else
+    void validate() const {}
+#endif
+
+    int getCacheCountLimit() const { return fCacheCountLimit; }
+    int setCacheCountLimit(int limit);
+
+    size_t  getCacheSizeLimit() const { return fCacheSizeLimit; }
+    size_t  setCacheSizeLimit(size_t limit);
+
+    // returns true if this cache is over-budget either due to size limit
+    // or count limit.
+    bool isOverBudget() const {
+        return fCacheCount > fCacheCountLimit ||
+               fTotalMemoryUsed > fCacheSizeLimit;
+    }
+
+    void purgeAll(); // does not change budget
+
+    // call when a glyphcache is available for caching (i.e. not in use)
+    void attachCacheToHead(SkGlyphCache*);
+    
+    // can only be called when the mutex is already held
+    void internalDetachCache(SkGlyphCache*);
+    void internalAttachCacheToHead(SkGlyphCache*);
+
+    // 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:
+    SkGlyphCache* fHead;
+    size_t  fTotalMemoryUsed;
+    size_t  fCacheSizeLimit;
+    int32_t fCacheCountLimit;
+    int32_t fCacheCount;
+    
+    // Checkout budgets, modulated by the specified min-bytes-needed-to-purge,
+    // and attempt to purge caches to match.
+    // Returns number of bytes freed.
+    size_t internalPurge(size_t minBytesNeeded = 0);
+
+    static void* CreateTLS() {
+        return SkNEW_ARGS(SkGlyphCache_Globals, (kNo_UseMutex));
+    }
+    
+    static void DeleteTLS(void* ptr) {
+        SkDELETE((SkGlyphCache_Globals*)ptr);
+    }
+};
+
+#endif