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

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

Issue 1457123002: Make block size a template parameter of SkTLList (Closed) Base URL: https://skia.googlesource.com/skia.git@forward
Patch Set: another missing typename 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 | « gm/convexpolyeffect.cpp ('k') | src/gpu/GrClipMaskManager.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 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
11 #include "SkTInternalLList.h" 11 #include "SkTInternalLList.h"
12 #include "SkTypes.h" 12 #include "SkTypes.h"
13 #include <utility> 13 #include <utility>
14 14
15 template <typename T> class SkTLList;
16 template <typename T>
17 inline void* operator new(size_t, SkTLList<T>* list,
18 typename SkTLList<T>::Placement placement,
19 const typename SkTLList<T>::Iter& location);
20
21 /** Doubly-linked list of objects. The objects' lifetimes are controlled by the list. I.e. the 15 /** Doubly-linked list of objects. The objects' lifetimes are controlled by the list. I.e. the
22 the list creates the objects and they are deleted upon removal. This class b lock-allocates 16 the list creates the objects and they are deleted upon removal. This class b lock-allocates
23 space for entries based on a param passed to the constructor. 17 space for entries based on a param passed to the constructor.
24 18
25 Elements of the list can be constructed in place using the following macros: 19 Elements of the list can be constructed in place using the following macros:
26 SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args) 20 SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args)
27 SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args) 21 SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args)
28 where list is a SkTLList<type_name>*, location is an iterator, and args is t he paren-surrounded 22 where list is a SkTLList<type_name>*, location is an iterator, and args is t he paren-surrounded
29 constructor arguments for type_name. These macros behave like addBefore() an d addAfter(). 23 constructor arguments for type_name. These macros behave like addBefore() an d addAfter().
24
25 allocCnt is the number of objects to allocate as a group. In the worst case fragmentation
26 each object is using the space required for allocCnt unfragmented objects.
30 */ 27 */
31 template <typename T> 28 template <typename T, unsigned int N> class SkTLList : SkNoncopyable {
32 class SkTLList : SkNoncopyable {
33 private: 29 private:
34 struct Block; 30 struct Block;
35 struct Node { 31 struct Node {
36 char fObj[sizeof(T)]; 32 char fObj[sizeof(T)];
37 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node); 33 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node);
38 Block* fBlock; // owning block. 34 Block* fBlock; // owning block.
39 }; 35 };
40 typedef SkTInternalLList<Node> NodeList; 36 typedef SkTInternalLList<Node> NodeList;
41 37
42 public: 38 public:
43
44 class Iter; 39 class Iter;
45 40
46 /** allocCnt is the number of objects to allocate as a group. In the worst c ase fragmentation 41 SkTLList() : fCount(0) {
47 each object is using the space required for allocCnt unfragmented object s. */
48 SkTLList(int allocCnt = 1) : fCount(0), fAllocCnt(allocCnt) {
49 SkASSERT(allocCnt > 0);
50 this->validate(); 42 this->validate();
51 } 43 }
52 44
53 ~SkTLList() { 45 ~SkTLList() {
54 this->validate(); 46 this->validate();
55 typename NodeList::Iter iter; 47 typename NodeList::Iter iter;
56 Node* node = iter.init(fList, Iter::kHead_IterStart); 48 Node* node = iter.init(fList, Iter::kHead_IterStart);
57 while (node) { 49 while (node) {
58 SkTCast<T*>(node->fObj)->~T(); 50 SkTCast<T*>(node->fObj)->~T();
59 Block* block = node->fBlock; 51 Block* block = node->fBlock;
60 node = iter.next(); 52 node = iter.next();
61 if (0 == --block->fNodesInUse) { 53 if (0 == --block->fNodesInUse) {
62 for (int i = 0; i < fAllocCnt; ++i) { 54 for (unsigned int i = 0; i < N; ++i) {
63 block->fNodes[i].~Node(); 55 block->fNodes[i].~Node();
64 } 56 }
65 sk_free(block); 57 sk_free(block);
66 } 58 }
67 } 59 }
68 } 60 }
69 61
70 /** Adds a new element to the list at the head. */ 62 /** Adds a new element to the list at the head. */
71 template <typename... Args> T* addToHead(Args&&... args) { 63 template <typename... Args> T* addToHead(Args&&... args) {
72 this->validate(); 64 this->validate();
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 return reinterpret_cast<T*>(node->fObj); 206 return reinterpret_cast<T*>(node->fObj);
215 } else { 207 } else {
216 return nullptr; 208 return nullptr;
217 } 209 }
218 } 210 }
219 }; 211 };
220 212
221 private: 213 private:
222 struct Block { 214 struct Block {
223 int fNodesInUse; 215 int fNodesInUse;
224 Node fNodes[1]; 216 Node fNodes[N];
225 }; 217 };
226 218
227 size_t blockSize() const { return sizeof(Block) + sizeof(Node) * (fAllocCnt- 1); }
228
229 Node* createNode() { 219 Node* createNode() {
230 Node* node = fFreeList.head(); 220 Node* node = fFreeList.head();
231 if (node) { 221 if (node) {
232 fFreeList.remove(node); 222 fFreeList.remove(node);
233 ++node->fBlock->fNodesInUse; 223 ++node->fBlock->fNodesInUse;
234 } else { 224 } else {
235 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(this->blockS ize())); 225 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(sizeof(Block )));
236 node = &block->fNodes[0]; 226 node = &block->fNodes[0];
237 new (node) Node; 227 new (node) Node;
238 node->fBlock = block; 228 node->fBlock = block;
239 block->fNodesInUse = 1; 229 block->fNodesInUse = 1;
240 for (int i = 1; i < fAllocCnt; ++i) { 230 for (unsigned int i = 1; i < N; ++i) {
241 new (block->fNodes + i) Node; 231 new (block->fNodes + i) Node;
242 fFreeList.addToHead(block->fNodes + i); 232 fFreeList.addToHead(block->fNodes + i);
243 block->fNodes[i].fBlock = block; 233 block->fNodes[i].fBlock = block;
244 } 234 }
245 } 235 }
246 ++fCount; 236 ++fCount;
247 return node; 237 return node;
248 } 238 }
249 239
250 void removeNode(Node* node) { 240 void removeNode(Node* node) {
251 SkASSERT(node); 241 SkASSERT(node);
252 fList.remove(node); 242 fList.remove(node);
253 SkTCast<T*>(node->fObj)->~T(); 243 SkTCast<T*>(node->fObj)->~T();
254 if (0 == --node->fBlock->fNodesInUse) { 244 if (0 == --node->fBlock->fNodesInUse) {
255 Block* block = node->fBlock; 245 Block* block = node->fBlock;
256 for (int i = 0; i < fAllocCnt; ++i) { 246 for (unsigned int i = 0; i < N; ++i) {
257 if (block->fNodes + i != node) { 247 if (block->fNodes + i != node) {
258 fFreeList.remove(block->fNodes + i); 248 fFreeList.remove(block->fNodes + i);
259 } 249 }
260 block->fNodes[i].~Node(); 250 block->fNodes[i].~Node();
261 } 251 }
262 sk_free(block); 252 sk_free(block);
263 } else { 253 } else {
264 fFreeList.addToHead(node); 254 fFreeList.addToHead(node);
265 } 255 }
266 --fCount; 256 --fCount;
267 this->validate(); 257 this->validate();
268 } 258 }
269 259
270 void validate() const { 260 void validate() const {
271 #ifdef SK_DEBUG 261 #ifdef SK_DEBUG
272 SkASSERT((0 == fCount) == fList.isEmpty()); 262 SkASSERT((0 == fCount) == fList.isEmpty());
273 SkASSERT((0 != fCount) || fFreeList.isEmpty()); 263 SkASSERT((0 != fCount) || fFreeList.isEmpty());
274 264
275 fList.validate(); 265 fList.validate();
276 fFreeList.validate(); 266 fFreeList.validate();
277 typename NodeList::Iter iter; 267 typename NodeList::Iter iter;
278 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart); 268 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart);
279 while (freeNode) { 269 while (freeNode) {
280 SkASSERT(fFreeList.isInList(freeNode)); 270 SkASSERT(fFreeList.isInList(freeNode));
281 Block* block = freeNode->fBlock; 271 Block* block = freeNode->fBlock;
282 SkASSERT(block->fNodesInUse > 0 && block->fNodesInUse < fAllocCnt); 272 SkASSERT(block->fNodesInUse > 0 && (unsigned)block->fNodesInUse < N) ;
283 273
284 int activeCnt = 0; 274 int activeCnt = 0;
285 int freeCnt = 0; 275 int freeCnt = 0;
286 for (int i = 0; i < fAllocCnt; ++i) { 276 for (unsigned int i = 0; i < N; ++i) {
287 bool free = fFreeList.isInList(block->fNodes + i); 277 bool free = fFreeList.isInList(block->fNodes + i);
288 bool active = fList.isInList(block->fNodes + i); 278 bool active = fList.isInList(block->fNodes + i);
289 SkASSERT(free != active); 279 SkASSERT(free != active);
290 activeCnt += active; 280 activeCnt += active;
291 freeCnt += free; 281 freeCnt += free;
292 } 282 }
293 SkASSERT(activeCnt == block->fNodesInUse); 283 SkASSERT(activeCnt == block->fNodesInUse);
294 freeNode = iter.next(); 284 freeNode = iter.next();
295 } 285 }
296 286
297 int count = 0; 287 int count = 0;
298 Node* activeNode = iter.init(fList, Iter::kHead_IterStart); 288 Node* activeNode = iter.init(fList, Iter::kHead_IterStart);
299 while (activeNode) { 289 while (activeNode) {
300 ++count; 290 ++count;
301 SkASSERT(fList.isInList(activeNode)); 291 SkASSERT(fList.isInList(activeNode));
302 Block* block = activeNode->fBlock; 292 Block* block = activeNode->fBlock;
303 SkASSERT(block->fNodesInUse > 0 && block->fNodesInUse <= fAllocCnt); 293 SkASSERT(block->fNodesInUse > 0 && (unsigned)block->fNodesInUse <= N );
304 294
305 int activeCnt = 0; 295 int activeCnt = 0;
306 int freeCnt = 0; 296 int freeCnt = 0;
307 for (int i = 0; i < fAllocCnt; ++i) { 297 for (unsigned int i = 0; i < N; ++i) {
308 bool free = fFreeList.isInList(block->fNodes + i); 298 bool free = fFreeList.isInList(block->fNodes + i);
309 bool active = fList.isInList(block->fNodes + i); 299 bool active = fList.isInList(block->fNodes + i);
310 SkASSERT(free != active); 300 SkASSERT(free != active);
311 activeCnt += active; 301 activeCnt += active;
312 freeCnt += free; 302 freeCnt += free;
313 } 303 }
314 SkASSERT(activeCnt == block->fNodesInUse); 304 SkASSERT(activeCnt == block->fNodesInUse);
315 activeNode = iter.next(); 305 activeNode = iter.next();
316 } 306 }
317 SkASSERT(count == fCount); 307 SkASSERT(count == fCount);
318 #endif 308 #endif
319 } 309 }
320 310
321 NodeList fList; 311 NodeList fList;
322 NodeList fFreeList; 312 NodeList fFreeList;
323 int fCount; 313 int fCount;
324 int fAllocCnt;
325
326 }; 314 };
327 315
328 #endif 316 #endif
OLDNEW
« no previous file with comments | « gm/convexpolyeffect.cpp ('k') | src/gpu/GrClipMaskManager.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698