OLD | NEW |
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 | 14 |
14 template <typename T> class SkTLList; | 15 template <typename T> class SkTLList; |
15 template <typename T> | 16 template <typename T> |
16 inline void* operator new(size_t, SkTLList<T>* list, | 17 inline void* operator new(size_t, SkTLList<T>* list, |
17 typename SkTLList<T>::Placement placement, | 18 typename SkTLList<T>::Placement placement, |
18 const typename SkTLList<T>::Iter& location); | 19 const typename SkTLList<T>::Iter& location); |
19 | 20 |
20 /** Doubly-linked list of objects. The objects' lifetimes are controlled by the
list. I.e. the | 21 /** Doubly-linked list of objects. The objects' lifetimes are controlled by the
list. I.e. the |
21 the list creates the objects and they are deleted upon removal. This class b
lock-allocates | 22 the list creates the objects and they are deleted upon removal. This class b
lock-allocates |
22 space for entries based on a param passed to the constructor. | 23 space for entries based on a param passed to the constructor. |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
59 node = iter.next(); | 60 node = iter.next(); |
60 if (0 == --block->fNodesInUse) { | 61 if (0 == --block->fNodesInUse) { |
61 for (int i = 0; i < fAllocCnt; ++i) { | 62 for (int i = 0; i < fAllocCnt; ++i) { |
62 block->fNodes[i].~Node(); | 63 block->fNodes[i].~Node(); |
63 } | 64 } |
64 sk_free(block); | 65 sk_free(block); |
65 } | 66 } |
66 } | 67 } |
67 } | 68 } |
68 | 69 |
69 T* addToHead(const T& t) { | 70 /** Adds a new element to the list at the head. */ |
| 71 template <typename... Args> T* addToHead(Args&&... args) { |
70 this->validate(); | 72 this->validate(); |
71 Node* node = this->createNode(); | 73 Node* node = this->createNode(); |
72 fList.addToHead(node); | 74 fList.addToHead(node); |
73 new (node->fObj) T(t); | |
74 this->validate(); | 75 this->validate(); |
75 return reinterpret_cast<T*>(node->fObj); | 76 return new (node->fObj) T(std::forward<Args>(args)...); |
76 } | 77 } |
77 | 78 |
78 T* addToHead() { | 79 /** Adds a new element to the list at the tail. */ |
79 this->validate(); | 80 template <typename... Args> T* addToTail(Args&&... args) { |
80 Node* node = this->createNode(); | |
81 fList.addToHead(node); | |
82 new (node->fObj) T; | |
83 this->validate(); | |
84 return reinterpret_cast<T*>(node->fObj); | |
85 } | |
86 | |
87 T* addToTail(const T& t) { | |
88 this->validate(); | 81 this->validate(); |
89 Node* node = this->createNode(); | 82 Node* node = this->createNode(); |
90 fList.addToTail(node); | 83 fList.addToTail(node); |
91 new (node->fObj) T(t); | |
92 this->validate(); | 84 this->validate(); |
93 return reinterpret_cast<T*>(node->fObj); | 85 return new (node->fObj) T(std::forward<Args>(args)...); |
94 } | |
95 | |
96 T* addToTail() { | |
97 this->validate(); | |
98 Node* node = this->createNode(); | |
99 fList.addToTail(node); | |
100 new (node->fObj) T; | |
101 this->validate(); | |
102 return reinterpret_cast<T*>(node->fObj); | |
103 } | 86 } |
104 | 87 |
105 /** Adds a new element to the list before the location indicated by the iter
ator. If the | 88 /** Adds a new element to the list before the location indicated by the iter
ator. If the |
106 iterator refers to a nullptr location then the new element is added at t
he tail */ | 89 iterator refers to a nullptr location then the new element is added at t
he tail */ |
107 T* addBefore(const T& t, const Iter& location) { | 90 template <typename... Args> T* addBefore(Iter location, Args&&... args) { |
108 return new (this->internalAddBefore(location)) T(t); | 91 this->validate(); |
| 92 Node* node = this->createNode(); |
| 93 fList.addBefore(node, location.getNode()); |
| 94 this->validate(); |
| 95 return new (node->fObj) T(std::forward<Args>(args)...); |
109 } | 96 } |
110 | 97 |
111 /** Adds a new element to the list after the location indicated by the itera
tor. If the | 98 /** Adds a new element to the list after the location indicated by the itera
tor. If the |
112 iterator refers to a nullptr location then the new element is added at t
he head */ | 99 iterator refers to a nullptr location then the new element is added at t
he head */ |
113 T* addAfter(const T& t, const Iter& location) { | 100 template <typename... Args> T* addAfter(Iter location, Args&&... args) { |
114 return new (this->internalAddAfter(location)) T(t); | 101 this->validate(); |
| 102 Node* node = this->createNode(); |
| 103 fList.addAfter(node, location.getNode()); |
| 104 this->validate(); |
| 105 return new (node->fObj) T(std::forward<Args>(args)...); |
115 } | 106 } |
116 | 107 |
117 /** Convenience methods for getting an iterator initialized to the head/tail
of the list. */ | 108 /** Convenience methods for getting an iterator initialized to the head/tail
of the list. */ |
118 Iter headIter() const { return Iter(*this, Iter::kHead_IterStart); } | 109 Iter headIter() const { return Iter(*this, Iter::kHead_IterStart); } |
119 Iter tailIter() const { return Iter(*this, Iter::kTail_IterStart); } | 110 Iter tailIter() const { return Iter(*this, Iter::kTail_IterStart); } |
120 | 111 |
121 T* head() { return Iter(*this, Iter::kHead_IterStart).get(); } | 112 T* head() { return Iter(*this, Iter::kHead_IterStart).get(); } |
122 T* tail() { return Iter(*this, Iter::kTail_IterStart).get(); } | 113 T* tail() { return Iter(*this, Iter::kTail_IterStart).get(); } |
123 const T* head() const { return Iter(*this, Iter::kHead_IterStart).get(); } | 114 const T* head() const { return Iter(*this, Iter::kHead_IterStart).get(); } |
124 const T* tail() const { return Iter(*this, Iter::kTail_IterStart).get(); } | 115 const T* tail() const { return Iter(*this, Iter::kTail_IterStart).get(); } |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
220 | 211 |
221 T* nodeToObj(Node* node) { | 212 T* nodeToObj(Node* node) { |
222 if (node) { | 213 if (node) { |
223 return reinterpret_cast<T*>(node->fObj); | 214 return reinterpret_cast<T*>(node->fObj); |
224 } else { | 215 } else { |
225 return nullptr; | 216 return nullptr; |
226 } | 217 } |
227 } | 218 } |
228 }; | 219 }; |
229 | 220 |
230 // For use with operator new | |
231 enum Placement { | |
232 kBefore_Placement, | |
233 kAfter_Placement, | |
234 }; | |
235 | |
236 private: | 221 private: |
237 struct Block { | 222 struct Block { |
238 int fNodesInUse; | 223 int fNodesInUse; |
239 Node fNodes[1]; | 224 Node fNodes[1]; |
240 }; | 225 }; |
241 | 226 |
242 size_t blockSize() const { return sizeof(Block) + sizeof(Node) * (fAllocCnt-
1); } | 227 size_t blockSize() const { return sizeof(Block) + sizeof(Node) * (fAllocCnt-
1); } |
243 | 228 |
244 Node* createNode() { | 229 Node* createNode() { |
245 Node* node = fFreeList.head(); | 230 Node* node = fFreeList.head(); |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
326 activeCnt += active; | 311 activeCnt += active; |
327 freeCnt += free; | 312 freeCnt += free; |
328 } | 313 } |
329 SkASSERT(activeCnt == block->fNodesInUse); | 314 SkASSERT(activeCnt == block->fNodesInUse); |
330 activeNode = iter.next(); | 315 activeNode = iter.next(); |
331 } | 316 } |
332 SkASSERT(count == fCount); | 317 SkASSERT(count == fCount); |
333 #endif | 318 #endif |
334 } | 319 } |
335 | 320 |
336 // Support in-place initializing of objects inserted into the list via opera
tor new. | |
337 friend void* operator new<T>(size_t, | |
338 SkTLList* list, | |
339 Placement placement, | |
340 const Iter& location); | |
341 | |
342 | |
343 // Helpers that insert the node and returns a pointer to where the new objec
t should be init'ed. | |
344 void* internalAddBefore(Iter location) { | |
345 this->validate(); | |
346 Node* node = this->createNode(); | |
347 fList.addBefore(node, location.getNode()); | |
348 this->validate(); | |
349 return node->fObj; | |
350 } | |
351 | |
352 void* internalAddAfter(Iter location) { | |
353 this->validate(); | |
354 Node* node = this->createNode(); | |
355 fList.addAfter(node, location.getNode()); | |
356 this->validate(); | |
357 return node->fObj; | |
358 } | |
359 | |
360 NodeList fList; | 321 NodeList fList; |
361 NodeList fFreeList; | 322 NodeList fFreeList; |
362 int fCount; | 323 int fCount; |
363 int fAllocCnt; | 324 int fAllocCnt; |
364 | 325 |
365 }; | 326 }; |
366 | 327 |
367 // Use the below macros rather than calling this directly | |
368 template <typename T> | |
369 void *operator new(size_t, SkTLList<T>* list, | |
370 typename SkTLList<T>::Placement placement, | |
371 const typename SkTLList<T>::Iter& location) { | |
372 SkASSERT(list); | |
373 if (SkTLList<T>::kBefore_Placement == placement) { | |
374 return list->internalAddBefore(location); | |
375 } else { | |
376 return list->internalAddAfter(location); | |
377 } | |
378 } | |
379 | |
380 // Skia doesn't use C++ exceptions but it may be compiled with them enabled. Hav
ing an op delete | |
381 // to match the op new silences warnings about missing op delete when a construc
tor throws an | |
382 // exception. | |
383 template <typename T> | |
384 void operator delete(void*, | |
385 SkTLList<T>*, | |
386 typename SkTLList<T>::Placement, | |
387 const typename SkTLList<T>::Iter&) { | |
388 SK_CRASH(); | |
389 } | |
390 | |
391 #define SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args) \ | |
392 (new ((list), SkTLList< type_name >::kBefore_Placement, (location)) type_nam
e args) | |
393 | |
394 #define SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args) \ | |
395 (new ((list), SkTLList< type_name >::kAfter_Placement, (location)) type_name
args) | |
396 | |
397 #define SkNEW_INSERT_AT_LLIST_HEAD(list, type_name, args) \ | |
398 SkNEW_INSERT_IN_LLIST_BEFORE((list), (list)->headIter(), type_name, args) | |
399 | |
400 #define SkNEW_INSERT_AT_LLIST_TAIL(list, type_name, args) \ | |
401 SkNEW_INSERT_IN_LLIST_AFTER((list), (list)->tailIter(), type_name, args) | |
402 | |
403 #endif | 328 #endif |
OLD | NEW |