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

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

Issue 1458703005: Make SkTLList prealloc its first block of nodes (Closed) Base URL: https://skia.googlesource.com/skia.git@nblock
Patch Set: rebase Created 5 years, 1 month 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 21 matching lines...) Expand all
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 SkTLList() : fCount(0) {
42 fFirstBlock.fNodesInUse = 0;
43 for (unsigned int i = 0; i < N; ++i) {
44 fFreeList.addToHead(fFirstBlock.fNodes + i);
45 fFirstBlock.fNodes[i].fBlock = &fFirstBlock;
46 }
42 this->validate(); 47 this->validate();
43 } 48 }
44 49
45 ~SkTLList() { 50 ~SkTLList() {
46 this->validate(); 51 this->validate();
47 typename NodeList::Iter iter; 52 typename NodeList::Iter iter;
48 Node* node = iter.init(fList, Iter::kHead_IterStart); 53 Node* node = iter.init(fList, Iter::kHead_IterStart);
49 while (node) { 54 while (node) {
50 SkTCast<T*>(node->fObj)->~T(); 55 SkTCast<T*>(node->fObj)->~T();
51 Block* block = node->fBlock; 56 Block* block = node->fBlock;
52 node = iter.next(); 57 node = iter.next();
53 if (0 == --block->fNodesInUse) { 58 if (0 == --block->fNodesInUse) {
54 for (unsigned int i = 0; i < N; ++i) { 59 for (unsigned int i = 0; i < N; ++i) {
55 block->fNodes[i].~Node(); 60 block->fNodes[i].~Node();
56 } 61 }
57 sk_free(block); 62 if (block != &fFirstBlock) {
63 sk_free(block);
64 }
58 } 65 }
59 } 66 }
60 } 67 }
61 68
62 /** Adds a new element to the list at the head. */ 69 /** Adds a new element to the list at the head. */
63 template <typename... Args> T* addToHead(Args&&... args) { 70 template <typename... Args> T* addToHead(Args&&... args) {
64 this->validate(); 71 this->validate();
65 Node* node = this->createNode(); 72 Node* node = this->createNode();
66 fList.addToHead(node); 73 fList.addToHead(node);
67 this->validate(); 74 this->validate();
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 int fNodesInUse; 222 int fNodesInUse;
216 Node fNodes[N]; 223 Node fNodes[N];
217 }; 224 };
218 225
219 Node* createNode() { 226 Node* createNode() {
220 Node* node = fFreeList.head(); 227 Node* node = fFreeList.head();
221 if (node) { 228 if (node) {
222 fFreeList.remove(node); 229 fFreeList.remove(node);
223 ++node->fBlock->fNodesInUse; 230 ++node->fBlock->fNodesInUse;
224 } else { 231 } else {
232 // Should not get here when count == 0 because we always have the pr eallocated first
233 // block.
234 SkASSERT(fCount > 0);
225 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(sizeof(Block ))); 235 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(sizeof(Block )));
226 node = &block->fNodes[0]; 236 node = &block->fNodes[0];
227 new (node) Node; 237 new (node) Node;
228 node->fBlock = block; 238 node->fBlock = block;
229 block->fNodesInUse = 1; 239 block->fNodesInUse = 1;
230 for (unsigned int i = 1; i < N; ++i) { 240 for (unsigned int i = 1; i < N; ++i) {
231 new (block->fNodes + i) Node; 241 new (block->fNodes + i) Node;
232 fFreeList.addToHead(block->fNodes + i); 242 fFreeList.addToHead(block->fNodes + i);
233 block->fNodes[i].fBlock = block; 243 block->fNodes[i].fBlock = block;
234 } 244 }
235 } 245 }
236 ++fCount; 246 ++fCount;
237 return node; 247 return node;
238 } 248 }
239 249
240 void removeNode(Node* node) { 250 void removeNode(Node* node) {
241 SkASSERT(node); 251 SkASSERT(node);
242 fList.remove(node); 252 fList.remove(node);
243 SkTCast<T*>(node->fObj)->~T(); 253 SkTCast<T*>(node->fObj)->~T();
244 if (0 == --node->fBlock->fNodesInUse) { 254 Block* block = node->fBlock;
245 Block* block = node->fBlock; 255 // Don't ever elease the first block, just add its nodes to the free lis t
256 if (0 == --block->fNodesInUse && block != &fFirstBlock) {
246 for (unsigned int i = 0; i < N; ++i) { 257 for (unsigned int i = 0; i < N; ++i) {
247 if (block->fNodes + i != node) { 258 if (block->fNodes + i != node) {
248 fFreeList.remove(block->fNodes + i); 259 fFreeList.remove(block->fNodes + i);
249 } 260 }
250 block->fNodes[i].~Node(); 261 block->fNodes[i].~Node();
251 } 262 }
252 sk_free(block); 263 sk_free(block);
253 } else { 264 } else {
254 fFreeList.addToHead(node); 265 fFreeList.addToHead(node);
255 } 266 }
256 --fCount; 267 --fCount;
257 this->validate(); 268 this->validate();
258 } 269 }
259 270
260 void validate() const { 271 void validate() const {
261 #ifdef SK_DEBUG 272 #ifdef SK_DEBUG
262 SkASSERT((0 == fCount) == fList.isEmpty()); 273 SkASSERT((0 == fCount) == fList.isEmpty());
263 SkASSERT((0 != fCount) || fFreeList.isEmpty()); 274 if (0 == fCount) {
264 275 // Should only have the nodes from the first block in the free list.
276 SkASSERT(fFreeList.countEntries() == N);
277 }
265 fList.validate(); 278 fList.validate();
266 fFreeList.validate(); 279 fFreeList.validate();
267 typename NodeList::Iter iter; 280 typename NodeList::Iter iter;
268 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart); 281 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart);
269 while (freeNode) { 282 while (freeNode) {
270 SkASSERT(fFreeList.isInList(freeNode)); 283 SkASSERT(fFreeList.isInList(freeNode));
271 Block* block = freeNode->fBlock; 284 Block* block = freeNode->fBlock;
272 SkASSERT(block->fNodesInUse > 0 && (unsigned)block->fNodesInUse < N) ; 285 // Only the first block is allowed to have all its nodes in the free list.
273 286 SkASSERT(block->fNodesInUse > 0 || block == &fFirstBlock);
287 SkASSERT((unsigned)block->fNodesInUse < N);
274 int activeCnt = 0; 288 int activeCnt = 0;
275 int freeCnt = 0; 289 int freeCnt = 0;
276 for (unsigned int i = 0; i < N; ++i) { 290 for (unsigned int i = 0; i < N; ++i) {
277 bool free = fFreeList.isInList(block->fNodes + i); 291 bool free = fFreeList.isInList(block->fNodes + i);
278 bool active = fList.isInList(block->fNodes + i); 292 bool active = fList.isInList(block->fNodes + i);
279 SkASSERT(free != active); 293 SkASSERT(free != active);
280 activeCnt += active; 294 activeCnt += active;
281 freeCnt += free; 295 freeCnt += free;
282 } 296 }
283 SkASSERT(activeCnt == block->fNodesInUse); 297 SkASSERT(activeCnt == block->fNodesInUse);
(...skipping 19 matching lines...) Expand all
303 } 317 }
304 SkASSERT(activeCnt == block->fNodesInUse); 318 SkASSERT(activeCnt == block->fNodesInUse);
305 activeNode = iter.next(); 319 activeNode = iter.next();
306 } 320 }
307 SkASSERT(count == fCount); 321 SkASSERT(count == fCount);
308 #endif 322 #endif
309 } 323 }
310 324
311 NodeList fList; 325 NodeList fList;
312 NodeList fFreeList; 326 NodeList fFreeList;
327 Block fFirstBlock;
313 int fCount; 328 int fCount;
314 }; 329 };
315 330
316 #endif 331 #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