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

Side by Side Diff: src/lazy/SkDiscardableMemoryPool.cpp

Issue 223403012: SkDiscardableMemoryPool to abstract class (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: AnotherPatchSet Created 6 years, 8 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 | « src/lazy/SkDiscardableMemoryPool.h ('k') | tests/CachedDecodingPixelRefTest.cpp » ('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 2013 Google Inc. 2 * Copyright 2013 Google Inc.
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 "SkDiscardableMemory.h"
8 #include "SkDiscardableMemoryPool.h" 9 #include "SkDiscardableMemoryPool.h"
9 #include "SkOnce.h" 10 #include "SkOnce.h"
11 #include "SkTInternalLList.h"
12 #include "SkThread.h"
10 13
11 // Note: 14 // Note:
12 // A PoolDiscardableMemory is memory that is counted in a pool. 15 // A PoolDiscardableMemory is memory that is counted in a pool.
13 // A DiscardableMemoryPool is a pool of PoolDiscardableMemorys. 16 // A DiscardableMemoryPool is a pool of PoolDiscardableMemorys.
14 17
18 namespace {
19
20 class PoolDiscardableMemory;
21
15 /** 22 /**
16 * A SkPoolDiscardableMemory is a SkDiscardableMemory that relies on 23 * This non-global pool can be used for unit tests to verify that the
17 * a SkDiscardableMemoryPool object to manage the memory. 24 * pool works.
18 */ 25 */
19 class SkPoolDiscardableMemory : public SkDiscardableMemory { 26 class DiscardableMemoryPool : public SkDiscardableMemoryPool {
20 public: 27 public:
21 SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool, 28 /**
29 * Without mutex, will be not be thread safe.
30 */
31 DiscardableMemoryPool(size_t budget, SkBaseMutex* mutex = NULL);
32 virtual ~DiscardableMemoryPool();
33
34 virtual SkDiscardableMemory* create(size_t bytes) SK_OVERRIDE;
35
36 virtual size_t getRAMUsed() SK_OVERRIDE;
37 virtual void setRAMBudget(size_t budget) SK_OVERRIDE;
38 virtual size_t getRAMBudget() SK_OVERRIDE { return fBudget; }
39
40 /** purges all unlocked DMs */
41 virtual void dumpPool() SK_OVERRIDE;
42
43 #if SK_LAZY_CACHE_STATS // Defined in SkDiscardableMemoryPool.h
44 virtual int getCacheHits() SK_OVERRIDE { return fCacheHits; }
45 virtual int getCacheMisses() SK_OVERRIDE { return fCacheMisses; }
46 virtual void resetCacheHitsAndMisses() SK_OVERRIDE {
47 fCacheHits = fCacheMisses = 0;
48 }
49 int fCacheHits;
50 int fCacheMisses;
51 #endif // SK_LAZY_CACHE_STATS
52
53 private:
54 SkBaseMutex* fMutex;
55 size_t fBudget;
56 size_t fUsed;
57 SkTInternalLList<PoolDiscardableMemory> fList;
58
59 /** Function called to free memory if needed */
60 void dumpDownTo(size_t budget);
61 /** called by DiscardableMemoryPool upon destruction */
62 void free(PoolDiscardableMemory* dm);
63 /** called by DiscardableMemoryPool::lock() */
64 bool lock(PoolDiscardableMemory* dm);
65 /** called by DiscardableMemoryPool::unlock() */
66 void unlock(PoolDiscardableMemory* dm);
67
68 friend class PoolDiscardableMemory;
69
70 typedef SkDiscardableMemory::Factory INHERITED;
71 };
72
73 /**
74 * A PoolDiscardableMemory is a SkDiscardableMemory that relies on
75 * a DiscardableMemoryPool object to manage the memory.
76 */
77 class PoolDiscardableMemory : public SkDiscardableMemory {
78 public:
79 PoolDiscardableMemory(DiscardableMemoryPool* pool,
22 void* pointer, size_t bytes); 80 void* pointer, size_t bytes);
23 virtual ~SkPoolDiscardableMemory(); 81 virtual ~PoolDiscardableMemory();
24 virtual bool lock() SK_OVERRIDE; 82 virtual bool lock() SK_OVERRIDE;
25 virtual void* data() SK_OVERRIDE; 83 virtual void* data() SK_OVERRIDE;
26 virtual void unlock() SK_OVERRIDE; 84 virtual void unlock() SK_OVERRIDE;
27 friend class SkDiscardableMemoryPool; 85 friend class DiscardableMemoryPool;
28 private: 86 private:
29 SK_DECLARE_INTERNAL_LLIST_INTERFACE(SkPoolDiscardableMemory); 87 SK_DECLARE_INTERNAL_LLIST_INTERFACE(PoolDiscardableMemory);
30 SkDiscardableMemoryPool* const fPool; 88 DiscardableMemoryPool* const fPool;
31 bool fLocked; 89 bool fLocked;
32 void* fPointer; 90 void* fPointer;
33 const size_t fBytes; 91 const size_t fBytes;
34 }; 92 };
35 93
36 SkPoolDiscardableMemory::SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool, 94 PoolDiscardableMemory::PoolDiscardableMemory(DiscardableMemoryPool* pool,
37 void* pointer, 95 void* pointer,
38 size_t bytes) 96 size_t bytes)
39 : fPool(pool) 97 : fPool(pool)
40 , fLocked(true) 98 , fLocked(true)
41 , fPointer(pointer) 99 , fPointer(pointer)
42 , fBytes(bytes) { 100 , fBytes(bytes) {
43 SkASSERT(fPool != NULL); 101 SkASSERT(fPool != NULL);
44 SkASSERT(fPointer != NULL); 102 SkASSERT(fPointer != NULL);
45 SkASSERT(fBytes > 0); 103 SkASSERT(fBytes > 0);
46 fPool->ref(); 104 fPool->ref();
47 } 105 }
48 106
49 SkPoolDiscardableMemory::~SkPoolDiscardableMemory() { 107 PoolDiscardableMemory::~PoolDiscardableMemory() {
50 SkASSERT(!fLocked); // contract for SkDiscardableMemory 108 SkASSERT(!fLocked); // contract for SkDiscardableMemory
51 fPool->free(this); 109 fPool->free(this);
52 fPool->unref(); 110 fPool->unref();
53 } 111 }
54 112
55 bool SkPoolDiscardableMemory::lock() { 113 bool PoolDiscardableMemory::lock() {
56 SkASSERT(!fLocked); // contract for SkDiscardableMemory 114 SkASSERT(!fLocked); // contract for SkDiscardableMemory
57 return fPool->lock(this); 115 return fPool->lock(this);
58 } 116 }
59 117
60 void* SkPoolDiscardableMemory::data() { 118 void* PoolDiscardableMemory::data() {
61 SkASSERT(fLocked); // contract for SkDiscardableMemory 119 SkASSERT(fLocked); // contract for SkDiscardableMemory
62 return fPointer; 120 return fPointer;
63 } 121 }
64 122
65 void SkPoolDiscardableMemory::unlock() { 123 void PoolDiscardableMemory::unlock() {
66 SkASSERT(fLocked); // contract for SkDiscardableMemory 124 SkASSERT(fLocked); // contract for SkDiscardableMemory
67 fPool->unlock(this); 125 fPool->unlock(this);
68 } 126 }
69 127
70 //////////////////////////////////////////////////////////////////////////////// 128 ////////////////////////////////////////////////////////////////////////////////
71 129
72 SkDiscardableMemoryPool::SkDiscardableMemoryPool(size_t budget, 130 DiscardableMemoryPool::DiscardableMemoryPool(size_t budget,
73 SkBaseMutex* mutex) 131 SkBaseMutex* mutex)
74 : fMutex(mutex) 132 : fMutex(mutex)
75 , fBudget(budget) 133 , fBudget(budget)
76 , fUsed(0) { 134 , fUsed(0) {
77 #if LAZY_CACHE_STATS 135 #if SK_LAZY_CACHE_STATS
78 fCacheHits = 0; 136 fCacheHits = 0;
79 fCacheMisses = 0; 137 fCacheMisses = 0;
80 #endif // LAZY_CACHE_STATS 138 #endif // SK_LAZY_CACHE_STATS
81 } 139 }
82 SkDiscardableMemoryPool::~SkDiscardableMemoryPool() { 140 DiscardableMemoryPool::~DiscardableMemoryPool() {
83 // SkPoolDiscardableMemory objects that belong to this pool are 141 // PoolDiscardableMemory objects that belong to this pool are
84 // always deleted before deleting this pool since each one has a 142 // always deleted before deleting this pool since each one has a
85 // ref to the pool. 143 // ref to the pool.
86 SkASSERT(fList.isEmpty()); 144 SkASSERT(fList.isEmpty());
87 } 145 }
88 146
89 void SkDiscardableMemoryPool::dumpDownTo(size_t budget) { 147 void DiscardableMemoryPool::dumpDownTo(size_t budget) {
90 // assert((NULL = fMutex) || fMutex->isLocked()); 148 // assert((NULL = fMutex) || fMutex->isLocked());
91 // TODO(halcanary) implement bool fMutex::isLocked(). 149 // TODO(halcanary) implement bool fMutex::isLocked().
92 // WARNING: only call this function after aquiring lock. 150 // WARNING: only call this function after aquiring lock.
93 if (fUsed <= budget) { 151 if (fUsed <= budget) {
94 return; 152 return;
95 } 153 }
96 typedef SkTInternalLList<SkPoolDiscardableMemory>::Iter Iter; 154 typedef SkTInternalLList<PoolDiscardableMemory>::Iter Iter;
97 Iter iter; 155 Iter iter;
98 SkPoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart); 156 PoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
99 while ((fUsed > budget) && (NULL != cur)) { 157 while ((fUsed > budget) && (NULL != cur)) {
100 if (!cur->fLocked) { 158 if (!cur->fLocked) {
101 SkPoolDiscardableMemory* dm = cur; 159 PoolDiscardableMemory* dm = cur;
102 SkASSERT(dm->fPointer != NULL); 160 SkASSERT(dm->fPointer != NULL);
103 sk_free(dm->fPointer); 161 sk_free(dm->fPointer);
104 dm->fPointer = NULL; 162 dm->fPointer = NULL;
105 SkASSERT(fUsed >= dm->fBytes); 163 SkASSERT(fUsed >= dm->fBytes);
106 fUsed -= dm->fBytes; 164 fUsed -= dm->fBytes;
107 cur = iter.prev(); 165 cur = iter.prev();
108 // Purged DMs are taken out of the list. This saves times 166 // Purged DMs are taken out of the list. This saves times
109 // looking them up. Purged DMs are NOT deleted. 167 // looking them up. Purged DMs are NOT deleted.
110 fList.remove(dm); 168 fList.remove(dm);
111 } else { 169 } else {
112 cur = iter.prev(); 170 cur = iter.prev();
113 } 171 }
114 } 172 }
115 } 173 }
116 174
117 SkDiscardableMemory* SkDiscardableMemoryPool::create(size_t bytes) { 175 SkDiscardableMemory* DiscardableMemoryPool::create(size_t bytes) {
118 void* addr = sk_malloc_flags(bytes, 0); 176 void* addr = sk_malloc_flags(bytes, 0);
119 if (NULL == addr) { 177 if (NULL == addr) {
120 return NULL; 178 return NULL;
121 } 179 }
122 SkPoolDiscardableMemory* dm = SkNEW_ARGS(SkPoolDiscardableMemory, 180 PoolDiscardableMemory* dm = SkNEW_ARGS(PoolDiscardableMemory,
123 (this, addr, bytes)); 181 (this, addr, bytes));
124 SkAutoMutexAcquire autoMutexAcquire(fMutex); 182 SkAutoMutexAcquire autoMutexAcquire(fMutex);
125 fList.addToHead(dm); 183 fList.addToHead(dm);
126 fUsed += bytes; 184 fUsed += bytes;
127 this->dumpDownTo(fBudget); 185 this->dumpDownTo(fBudget);
128 return dm; 186 return dm;
129 } 187 }
130 188
131 void SkDiscardableMemoryPool::free(SkPoolDiscardableMemory* dm) { 189 void DiscardableMemoryPool::free(PoolDiscardableMemory* dm) {
132 // This is called by dm's destructor. 190 // This is called by dm's destructor.
133 if (dm->fPointer != NULL) { 191 if (dm->fPointer != NULL) {
134 SkAutoMutexAcquire autoMutexAcquire(fMutex); 192 SkAutoMutexAcquire autoMutexAcquire(fMutex);
135 sk_free(dm->fPointer); 193 sk_free(dm->fPointer);
136 dm->fPointer = NULL; 194 dm->fPointer = NULL;
137 SkASSERT(fUsed >= dm->fBytes); 195 SkASSERT(fUsed >= dm->fBytes);
138 fUsed -= dm->fBytes; 196 fUsed -= dm->fBytes;
139 fList.remove(dm); 197 fList.remove(dm);
140 } else { 198 } else {
141 SkASSERT(!fList.isInList(dm)); 199 SkASSERT(!fList.isInList(dm));
142 } 200 }
143 } 201 }
144 202
145 bool SkDiscardableMemoryPool::lock(SkPoolDiscardableMemory* dm) { 203 bool DiscardableMemoryPool::lock(PoolDiscardableMemory* dm) {
146 SkASSERT(dm != NULL); 204 SkASSERT(dm != NULL);
147 if (NULL == dm->fPointer) { 205 if (NULL == dm->fPointer) {
148 #if LAZY_CACHE_STATS 206 #if SK_LAZY_CACHE_STATS
149 SkAutoMutexAcquire autoMutexAcquire(fMutex); 207 SkAutoMutexAcquire autoMutexAcquire(fMutex);
150 ++fCacheMisses; 208 ++fCacheMisses;
151 #endif // LAZY_CACHE_STATS 209 #endif // SK_LAZY_CACHE_STATS
152 return false; 210 return false;
153 } 211 }
154 SkAutoMutexAcquire autoMutexAcquire(fMutex); 212 SkAutoMutexAcquire autoMutexAcquire(fMutex);
155 if (NULL == dm->fPointer) { 213 if (NULL == dm->fPointer) {
156 // May have been purged while waiting for lock. 214 // May have been purged while waiting for lock.
157 #if LAZY_CACHE_STATS 215 #if SK_LAZY_CACHE_STATS
158 ++fCacheMisses; 216 ++fCacheMisses;
159 #endif // LAZY_CACHE_STATS 217 #endif // SK_LAZY_CACHE_STATS
160 return false; 218 return false;
161 } 219 }
162 dm->fLocked = true; 220 dm->fLocked = true;
163 fList.remove(dm); 221 fList.remove(dm);
164 fList.addToHead(dm); 222 fList.addToHead(dm);
165 #if LAZY_CACHE_STATS 223 #if SK_LAZY_CACHE_STATS
166 ++fCacheHits; 224 ++fCacheHits;
167 #endif // LAZY_CACHE_STATS 225 #endif // SK_LAZY_CACHE_STATS
168 return true; 226 return true;
169 } 227 }
170 228
171 void SkDiscardableMemoryPool::unlock(SkPoolDiscardableMemory* dm) { 229 void DiscardableMemoryPool::unlock(PoolDiscardableMemory* dm) {
172 SkASSERT(dm != NULL); 230 SkASSERT(dm != NULL);
173 SkAutoMutexAcquire autoMutexAcquire(fMutex); 231 SkAutoMutexAcquire autoMutexAcquire(fMutex);
174 dm->fLocked = false; 232 dm->fLocked = false;
175 this->dumpDownTo(fBudget); 233 this->dumpDownTo(fBudget);
176 } 234 }
177 235
178 size_t SkDiscardableMemoryPool::getRAMUsed() { 236 size_t DiscardableMemoryPool::getRAMUsed() {
179 return fUsed; 237 return fUsed;
180 } 238 }
181 void SkDiscardableMemoryPool::setRAMBudget(size_t budget) { 239 void DiscardableMemoryPool::setRAMBudget(size_t budget) {
182 SkAutoMutexAcquire autoMutexAcquire(fMutex); 240 SkAutoMutexAcquire autoMutexAcquire(fMutex);
183 fBudget = budget; 241 fBudget = budget;
184 this->dumpDownTo(fBudget); 242 this->dumpDownTo(fBudget);
185 } 243 }
186 void SkDiscardableMemoryPool::dumpPool() { 244 void DiscardableMemoryPool::dumpPool() {
187 SkAutoMutexAcquire autoMutexAcquire(fMutex); 245 SkAutoMutexAcquire autoMutexAcquire(fMutex);
188 this->dumpDownTo(0); 246 this->dumpDownTo(0);
189 } 247 }
190 248
191 //////////////////////////////////////////////////////////////////////////////// 249 ////////////////////////////////////////////////////////////////////////////////
192 SK_DECLARE_STATIC_MUTEX(gMutex); 250 SK_DECLARE_STATIC_MUTEX(gMutex);
193 static void create_pool(SkDiscardableMemoryPool** pool) { 251 SkDiscardableMemoryPool* gPool = NULL;
194 SkASSERT(NULL == *pool); 252 void create_global_pool(int) {
195 *pool = SkNEW_ARGS(SkDiscardableMemoryPool, 253 SkASSERT(NULL == gPool);
196 (SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE, 254 gPool = SkDiscardableMemoryPool::Create(
197 &gMutex)); 255 SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE, &gMutex);
198 } 256 }
257 void cleanup_global_pool() {
258 gPool->unref();
259 }
260 } // namespace
261
262 SkDiscardableMemoryPool* SkDiscardableMemoryPool::Create(
263 size_t size, SkBaseMutex* mutex) {
264 return SkNEW_ARGS(DiscardableMemoryPool, (size, mutex));
265 }
266
199 SkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() { 267 SkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() {
200 static SkDiscardableMemoryPool* gPool(NULL);
201 SK_DECLARE_STATIC_ONCE(create_pool_once); 268 SK_DECLARE_STATIC_ONCE(create_pool_once);
202 SkOnce(&create_pool_once, create_pool, &gPool); 269 SkOnce(&create_pool_once, create_global_pool, 0, &cleanup_global_pool);
203 SkASSERT(NULL != gPool); 270 SkASSERT(NULL != gPool);
204 return gPool; 271 return gPool;
205 } 272 }
206 273
207 //////////////////////////////////////////////////////////////////////////////// 274 ////////////////////////////////////////////////////////////////////////////////
OLDNEW
« no previous file with comments | « src/lazy/SkDiscardableMemoryPool.h ('k') | tests/CachedDecodingPixelRefTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698