1 /*
2  * Copyright 2010 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkGlyphCache_Globals_DEFINED
9 #define SkGlyphCache_Globals_DEFINED
10 
11 #include "SkGlyphCache.h"
12 #include "SkTLS.h"
13 
14 #ifndef SK_DEFAULT_FONT_CACHE_COUNT_LIMIT
15     #define SK_DEFAULT_FONT_CACHE_COUNT_LIMIT   2048
16 #endif
17 
18 #ifndef SK_DEFAULT_FONT_CACHE_LIMIT
19     #define SK_DEFAULT_FONT_CACHE_LIMIT     (2 * 1024 * 1024)
20 #endif
21 
22 ///////////////////////////////////////////////////////////////////////////////
23 
24 class SkMutex;
25 
26 class SkGlyphCache_Globals {
27 public:
28     enum UseMutex {
29         kNo_UseMutex,  // thread-local cache
30         kYes_UseMutex  // shared cache
31     };
32 
SkGlyphCache_Globals(UseMutex um)33     SkGlyphCache_Globals(UseMutex um) {
34         fHead = NULL;
35         fTotalMemoryUsed = 0;
36         fCacheSizeLimit = SK_DEFAULT_FONT_CACHE_LIMIT;
37         fCacheCount = 0;
38         fCacheCountLimit = SK_DEFAULT_FONT_CACHE_COUNT_LIMIT;
39 
40         fMutex = (kYes_UseMutex == um) ? SkNEW(SkMutex) : NULL;
41     }
42 
~SkGlyphCache_Globals()43     ~SkGlyphCache_Globals() {
44         SkGlyphCache* cache = fHead;
45         while (cache) {
46             SkGlyphCache* next = cache->fNext;
47             SkDELETE(cache);
48             cache = next;
49         }
50 
51         SkDELETE(fMutex);
52     }
53 
54     SkMutex*        fMutex;
55 
internalGetHead()56     SkGlyphCache* internalGetHead() const { return fHead; }
57     SkGlyphCache* internalGetTail() const;
58 
getTotalMemoryUsed()59     size_t getTotalMemoryUsed() const { return fTotalMemoryUsed; }
getCacheCountUsed()60     int getCacheCountUsed() const { return fCacheCount; }
61 
62 #ifdef SK_DEBUG
63     void validate() const;
64 #else
validate()65     void validate() const {}
66 #endif
67 
getCacheCountLimit()68     int getCacheCountLimit() const { return fCacheCountLimit; }
69     int setCacheCountLimit(int limit);
70 
getCacheSizeLimit()71     size_t  getCacheSizeLimit() const { return fCacheSizeLimit; }
72     size_t  setCacheSizeLimit(size_t limit);
73 
74     // returns true if this cache is over-budget either due to size limit
75     // or count limit.
isOverBudget()76     bool isOverBudget() const {
77         return fCacheCount > fCacheCountLimit ||
78                fTotalMemoryUsed > fCacheSizeLimit;
79     }
80 
81     void purgeAll(); // does not change budget
82 
83     // call when a glyphcache is available for caching (i.e. not in use)
84     void attachCacheToHead(SkGlyphCache*);
85 
86     // can only be called when the mutex is already held
87     void internalDetachCache(SkGlyphCache*);
88     void internalAttachCacheToHead(SkGlyphCache*);
89 
90     // can return NULL
FindTLS()91     static SkGlyphCache_Globals* FindTLS() {
92         return (SkGlyphCache_Globals*)SkTLS::Find(CreateTLS);
93     }
94 
GetTLS()95     static SkGlyphCache_Globals& GetTLS() {
96         return *(SkGlyphCache_Globals*)SkTLS::Get(CreateTLS, DeleteTLS);
97     }
98 
DeleteTLS()99     static void DeleteTLS() { SkTLS::Delete(CreateTLS); }
100 
101 private:
102     SkGlyphCache* fHead;
103     size_t  fTotalMemoryUsed;
104     size_t  fCacheSizeLimit;
105     int32_t fCacheCountLimit;
106     int32_t fCacheCount;
107 
108     // Checkout budgets, modulated by the specified min-bytes-needed-to-purge,
109     // and attempt to purge caches to match.
110     // Returns number of bytes freed.
111     size_t internalPurge(size_t minBytesNeeded = 0);
112 
CreateTLS()113     static void* CreateTLS() {
114         return SkNEW_ARGS(SkGlyphCache_Globals, (kNo_UseMutex));
115     }
116 
DeleteTLS(void * ptr)117     static void DeleteTLS(void* ptr) {
118         SkDELETE((SkGlyphCache_Globals*)ptr);
119     }
120 };
121 
122 #endif
123