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

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

Issue 103033002: Big Cleanup: SkBitmapFactory, SkLazyPixelRef, SkImageCache (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: cleanup test Created 7 years 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 | Annotate | Revision Log
OLDNEW
(Empty)
1 /*
2 * Copyright 2013 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 #include "SkDiscardableMemoryPool.h"
9 #include "SkOnce.h"
10 #include "SkThread.h"
11
12 // Note:
13 // A PoolDiscardableMemory is memory that is counted in a pool.
14 // A DiscardableMemoryPool is a pool of PoolDiscardableMemorys.
15
16 /**
17 * A SkPoolDiscardableMemory is a SkDiscardableMemory that relies on
18 * a SkDiscardableMemoryPool object to manage the memory.
19 */
20 class SkPoolDiscardableMemory : public SkDiscardableMemory {
21 public:
22 SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
23 void* pointer, size_t bytes);
24 virtual ~SkPoolDiscardableMemory();
25 virtual bool lock() SK_OVERRIDE;
26 virtual void* data() SK_OVERRIDE;
27 virtual void unlock() SK_OVERRIDE;
28 friend class SkDiscardableMemoryPool;
29 private:
30 SK_DECLARE_INTERNAL_LLIST_INTERFACE(SkPoolDiscardableMemory);
31 SkDiscardableMemoryPool* const fPool;
32 bool fLocked;
33 void* fPointer;
34 const size_t fBytes;
35 };
36
37 SkPoolDiscardableMemory::SkPoolDiscardableMemory(SkDiscardableMemoryPool* pool,
38 void* pointer,
39 size_t bytes)
40 : fPool(pool)
41 , fLocked(true)
42 , fPointer(pointer)
43 , fBytes(bytes) {
44 SkASSERT(fPool != NULL);
45 SkASSERT(fPointer != NULL);
46 SkASSERT(fBytes > 0);
47 fPool->ref();
48 }
49
50 SkPoolDiscardableMemory::~SkPoolDiscardableMemory() {
51 fPool->free(this);
52 fPool->unref();
53 }
54
55 bool SkPoolDiscardableMemory::lock() {
56 return fPool->lock(this);
57 }
58
59 void* SkPoolDiscardableMemory::data() {
60 return fLocked ? fPointer : NULL;
61 }
62
63 void SkPoolDiscardableMemory::unlock() {
64 fPool->unlock(this);
65 }
66
67 ////////////////////////////////////////////////////////////////////////////////
68
69 SkDiscardableMemoryPool::SkDiscardableMemoryPool(size_t budget,
70 SkBaseMutex* mutex)
71 : fMutex(mutex)
72 , fBudget(budget)
73 , fUsed(0) {
74 #if LAZY_CACHE_STATS
75 fCacheHits = 0;
76 fCacheMisses = 0;
77 #endif // LAZY_CACHE_STATS
78 }
79 SkDiscardableMemoryPool::~SkDiscardableMemoryPool() {
80 // SkPoolDiscardableMemory objects that belong to this pool are
81 // always deleted before deleting this pool since each one has a
82 // ref to the pool.
83 SkASSERT(fList.isEmpty());
84 }
85
86 void SkDiscardableMemoryPool::dumpDownTo(size_t budget) {
87 // assert((NULL = fMutex) || fMutex->isLocked());
88 // TODO(halcanary) implement bool fMutex::isLocked().
89 // WARNING: only call this function after aquiring lock.
90 if (fUsed <= budget) {
91 return;
92 }
93 typedef SkTInternalLList<SkPoolDiscardableMemory>::Iter Iter;
94 Iter iter;
95 SkPoolDiscardableMemory* cur = iter.init(fList, Iter::kTail_IterStart);
96 while ((fUsed > budget) && (NULL != cur)) {
97 if (!cur->fLocked) {
98 SkPoolDiscardableMemory* dm = cur;
99 SkASSERT(dm->fPointer != NULL);
100 sk_free(dm->fPointer);
101 dm->fPointer = NULL;
102 SkASSERT(fUsed >= dm->fBytes);
103 fUsed -= dm->fBytes;
104 cur = iter.prev();
105 // Purged DMs are taken out of the list. This saves times
106 // looking them up. Purged DMs are NOT deleted.
107 fList.remove(dm);
108 } else {
109 cur = iter.prev();
110 }
111 }
112 }
113
114 SkDiscardableMemory* SkDiscardableMemoryPool::create(size_t bytes) {
115 void* addr = sk_malloc_flags(bytes, 0);
116 if (NULL == addr) {
117 return NULL;
118 }
119 SkPoolDiscardableMemory* dm = SkNEW_ARGS(SkPoolDiscardableMemory,
120 (this, addr, bytes));
121 SkAutoMutexAcquire autoMutexAcquire(fMutex);
122 fList.addToHead(dm);
123 fUsed += bytes;
124 this->dumpDownTo(fBudget);
125 return dm;
126 }
127
128 void SkDiscardableMemoryPool::free(SkPoolDiscardableMemory* dm) {
129 // This is called by dm's destructor.
130 if (dm->fPointer != NULL) {
131 SkAutoMutexAcquire autoMutexAcquire(fMutex);
132 sk_free(dm->fPointer);
133 dm->fPointer = NULL;
134 SkASSERT(fUsed >= dm->fBytes);
135 fUsed -= dm->fBytes;
136 fList.remove(dm);
137 } else {
138 SkASSERT(!fList.isInList(dm));
139 }
140 }
141
142 bool SkDiscardableMemoryPool::lock(SkPoolDiscardableMemory* dm) {
143 SkASSERT(dm != NULL);
144 if (NULL == dm->fPointer) {
145 #if LAZY_CACHE_STATS
146 SkAutoMutexAcquire autoMutexAcquire(fMutex);
147 ++fCacheMisses;
148 #endif // LAZY_CACHE_STATS
149 return false;
150 }
151 SkAutoMutexAcquire autoMutexAcquire(fMutex);
152 if (NULL == dm->fPointer) {
153 // May have been purged while waiting for lock.
154 #if LAZY_CACHE_STATS
155 ++fCacheMisses;
156 #endif // LAZY_CACHE_STATS
157 return false;
158 }
159 dm->fLocked = true;
160 fList.remove(dm);
161 fList.addToHead(dm);
162 #if LAZY_CACHE_STATS
163 ++fCacheHits;
164 #endif // LAZY_CACHE_STATS
165 return true;
166 }
167
168 void SkDiscardableMemoryPool::unlock(SkPoolDiscardableMemory* dm) {
169 SkASSERT(dm != NULL);
170 SkAutoMutexAcquire autoMutexAcquire(fMutex);
171 dm->fLocked = false;
172 this->dumpDownTo(fBudget);
173 }
174
175 size_t SkDiscardableMemoryPool::getRAMUsed() {
176 return fUsed;
177 }
178 void SkDiscardableMemoryPool::setRAMBudget(size_t budget) {
179 SkAutoMutexAcquire autoMutexAcquire(fMutex);
180 fBudget = budget;
181 this->dumpDownTo(fBudget);
182 }
183 void SkDiscardableMemoryPool::dumpPool() {
184 SkAutoMutexAcquire autoMutexAcquire(fMutex);
185 this->dumpDownTo(0);
186 }
187
188 ////////////////////////////////////////////////////////////////////////////////
189 SK_DECLARE_STATIC_MUTEX(gMutex);
190 static void create_pool(SkDiscardableMemoryPool** pool) {
191 SkASSERT(NULL == *pool);
192 *pool = SkNEW_ARGS(SkDiscardableMemoryPool,
193 (SK_DEFAULT_GLOBAL_DISCARDABLE_MEMORY_POOL_SIZE,
194 &gMutex));
195 }
196 SkDiscardableMemoryPool* SkGetGlobalDiscardableMemoryPool() {
197 static SkDiscardableMemoryPool* gPool(NULL);
198 SK_DECLARE_STATIC_ONCE(create_pool_once);
199 SkOnce(&create_pool_once, create_pool, &gPool);
200 SkASSERT(NULL != gPool);
201 return gPool;
202 }
203
204 ////////////////////////////////////////////////////////////////////////////////
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698