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

Side by Side Diff: src/core/SkTLList.h

Issue 2138043002: Delay initialization of free list in SkTLList until first use of list (Closed) Base URL: https://chromium.googlesource.com/skia.git@master
Patch Set: Improve comment Created 4 years, 5 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 | « no previous file | no next file » | 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 2012 Google Inc. 2 * Copyright 2012 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 #ifndef SkTLList_DEFINED 8 #ifndef SkTLList_DEFINED
9 #define SkTLList_DEFINED 9 #define SkTLList_DEFINED
10 10
(...skipping 20 matching lines...) Expand all
31 struct Node { 31 struct Node {
32 char fObj[sizeof(T)]; 32 char fObj[sizeof(T)];
33 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node); 33 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node);
34 Block* fBlock; // owning block. 34 Block* fBlock; // owning block.
35 }; 35 };
36 typedef SkTInternalLList<Node> NodeList; 36 typedef SkTInternalLList<Node> NodeList;
37 37
38 public: 38 public:
39 class Iter; 39 class Iter;
40 40
41 SkTLList() : fCount(0) { 41 // Having fCount initialized to -1 indicates that the first time we attempt to grab a free node
42 fFirstBlock.fNodesInUse = 0; 42 // all the nodes in the pre-allocated first block need to be inserted into t he free list. This
43 for (unsigned int i = 0; i < N; ++i) { 43 // allows us to skip that loop in instances when the list is never populated .
44 fFreeList.addToHead(fFirstBlock.fNodes + i); 44 SkTLList() : fCount(-1) {}
45 fFirstBlock.fNodes[i].fBlock = &fFirstBlock;
46 }
47 this->validate();
48 }
49 45
50 ~SkTLList() { 46 ~SkTLList() {
51 this->validate(); 47 this->validate();
52 typename NodeList::Iter iter; 48 typename NodeList::Iter iter;
53 Node* node = iter.init(fList, Iter::kHead_IterStart); 49 Node* node = iter.init(fList, Iter::kHead_IterStart);
54 while (node) { 50 while (node) {
55 SkTCast<T*>(node->fObj)->~T(); 51 SkTCast<T*>(node->fObj)->~T();
56 Block* block = node->fBlock; 52 Block* block = node->fBlock;
57 node = iter.next(); 53 node = iter.next();
58 if (0 == --block->fNodesInUse) { 54 if (0 == --block->fNodesInUse) {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
141 137
142 void reset() { 138 void reset() {
143 this->validate(); 139 this->validate();
144 Iter iter(*this, Iter::kHead_IterStart); 140 Iter iter(*this, Iter::kHead_IterStart);
145 while (iter.get()) { 141 while (iter.get()) {
146 Iter next = iter; 142 Iter next = iter;
147 next.next(); 143 next.next();
148 this->remove(iter.get()); 144 this->remove(iter.get());
149 iter = next; 145 iter = next;
150 } 146 }
151 SkASSERT(0 == fCount); 147 SkASSERT(0 == fCount || -1 == fCount);
152 this->validate(); 148 this->validate();
153 } 149 }
154 150
155 int count() const { return fCount; } 151 int count() const { return SkTMax(fCount ,0); }
156 bool isEmpty() const { this->validate(); return 0 == fCount; } 152 bool isEmpty() const { this->validate(); return 0 == fCount || -1 == fCount; }
157 153
158 bool operator== (const SkTLList& list) const { 154 bool operator== (const SkTLList& list) const {
159 if (this == &list) { 155 if (this == &list) {
160 return true; 156 return true;
161 } 157 }
162 if (fCount != list.fCount) { 158 // Call count() rather than use fCount because an empty list may have fC ount = 0 or -1.
159 if (this->count() != list.count()) {
163 return false; 160 return false;
164 } 161 }
165 for (Iter a(*this, Iter::kHead_IterStart), b(list, Iter::kHead_IterStart ); 162 for (Iter a(*this, Iter::kHead_IterStart), b(list, Iter::kHead_IterStart );
166 a.get(); 163 a.get();
167 a.next(), b.next()) { 164 a.next(), b.next()) {
168 SkASSERT(b.get()); // already checked that counts match. 165 SkASSERT(b.get()); // already checked that counts match.
169 if (!(*a.get() == *b.get())) { 166 if (!(*a.get() == *b.get())) {
170 return false; 167 return false;
171 } 168 }
172 } 169 }
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 } 213 }
217 } 214 }
218 }; 215 };
219 216
220 private: 217 private:
221 struct Block { 218 struct Block {
222 int fNodesInUse; 219 int fNodesInUse;
223 Node fNodes[N]; 220 Node fNodes[N];
224 }; 221 };
225 222
223 void delayedInit() {
224 SkASSERT(-1 == fCount);
225 fFirstBlock.fNodesInUse = 0;
226 for (unsigned int i = 0; i < N; ++i) {
227 fFreeList.addToHead(fFirstBlock.fNodes + i);
228 fFirstBlock.fNodes[i].fBlock = &fFirstBlock;
229 }
230 fCount = 0;
231 this->validate();
232 }
233
226 Node* createNode() { 234 Node* createNode() {
235 if (-1 == fCount) {
236 this->delayedInit();
237 }
227 Node* node = fFreeList.head(); 238 Node* node = fFreeList.head();
228 if (node) { 239 if (node) {
229 fFreeList.remove(node); 240 fFreeList.remove(node);
230 ++node->fBlock->fNodesInUse; 241 ++node->fBlock->fNodesInUse;
231 } else { 242 } else {
232 // Should not get here when count == 0 because we always have the pr eallocated first 243 // Should not get here when count == 0 because we always have the pr eallocated first
233 // block. 244 // block.
234 SkASSERT(fCount > 0); 245 SkASSERT(fCount > 0);
235 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(sizeof(Block ))); 246 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(sizeof(Block )));
236 node = &block->fNodes[0]; 247 node = &block->fNodes[0];
(...skipping 26 matching lines...) Expand all
263 sk_free(block); 274 sk_free(block);
264 } else { 275 } else {
265 fFreeList.addToHead(node); 276 fFreeList.addToHead(node);
266 } 277 }
267 --fCount; 278 --fCount;
268 this->validate(); 279 this->validate();
269 } 280 }
270 281
271 void validate() const { 282 void validate() const {
272 #ifdef SK_DEBUG 283 #ifdef SK_DEBUG
273 SkASSERT((0 == fCount) == fList.isEmpty()); 284 bool isEmpty = false;
274 if (0 == fCount) { 285 if (-1 == fCount) {
286 // We should not yet have initialized the free list.
287 SkASSERT(fFreeList.isEmpty());
288 isEmpty = true;
289 } else if (0 == fCount) {
275 // Should only have the nodes from the first block in the free list. 290 // Should only have the nodes from the first block in the free list.
276 SkASSERT(fFreeList.countEntries() == N); 291 SkASSERT(fFreeList.countEntries() == N);
292 isEmpty = true;
277 } 293 }
294 SkASSERT(isEmpty == fList.isEmpty());
278 fList.validate(); 295 fList.validate();
279 fFreeList.validate(); 296 fFreeList.validate();
280 typename NodeList::Iter iter; 297 typename NodeList::Iter iter;
281 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart); 298 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart);
282 while (freeNode) { 299 while (freeNode) {
283 SkASSERT(fFreeList.isInList(freeNode)); 300 SkASSERT(fFreeList.isInList(freeNode));
284 Block* block = freeNode->fBlock; 301 Block* block = freeNode->fBlock;
285 // Only the first block is allowed to have all its nodes in the free list. 302 // Only the first block is allowed to have all its nodes in the free list.
286 SkASSERT(block->fNodesInUse > 0 || block == &fFirstBlock); 303 SkASSERT(block->fNodesInUse > 0 || block == &fFirstBlock);
287 SkASSERT((unsigned)block->fNodesInUse < N); 304 SkASSERT((unsigned)block->fNodesInUse < N);
(...skipping 23 matching lines...) Expand all
311 for (unsigned int i = 0; i < N; ++i) { 328 for (unsigned int i = 0; i < N; ++i) {
312 bool free = fFreeList.isInList(block->fNodes + i); 329 bool free = fFreeList.isInList(block->fNodes + i);
313 bool active = fList.isInList(block->fNodes + i); 330 bool active = fList.isInList(block->fNodes + i);
314 SkASSERT(free != active); 331 SkASSERT(free != active);
315 activeCnt += active; 332 activeCnt += active;
316 freeCnt += free; 333 freeCnt += free;
317 } 334 }
318 SkASSERT(activeCnt == block->fNodesInUse); 335 SkASSERT(activeCnt == block->fNodesInUse);
319 activeNode = iter.next(); 336 activeNode = iter.next();
320 } 337 }
321 SkASSERT(count == fCount); 338 SkASSERT(count == fCount || (0 == count && -1 == fCount));
322 #endif 339 #endif
323 } 340 }
324 341
325 NodeList fList; 342 NodeList fList;
326 NodeList fFreeList; 343 NodeList fFreeList;
327 Block fFirstBlock; 344 Block fFirstBlock;
328 int fCount; 345 int fCount;
329 }; 346 };
330 347
331 #endif 348 #endif
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698