2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef SkTLList_DEFINED
9 #define SkTLList_DEFINED
11 #include "SkTInternalLList.h"
12 #include "SkTemplates.h"
14 template <typename T> class SkTLList;
16 inline void* operator new(size_t, SkTLList<T>* list,
17 typename SkTLList<T>::Placement placement,
18 const typename SkTLList<T>::Iter& location);
20 /** 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 block-allocates
22 space for entries based on a param passed to the constructor.
24 Elements of the list can be constructed in place using the following macros:
25 SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args)
26 SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args)
27 where list is a SkTLList<type_name>*, location is an iterator, and args is the paren-surrounded
28 constructor arguments for type_name. These macros behave like addBefore() and addAfter().
31 class SkTLList : public SkNoncopyable {
36 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node);
37 Block* fBlock; // owning block.
39 typedef SkTInternalLList<Node> NodeList;
45 /** allocCnt is the number of objects to allocate as a group. In the worst case fragmentation
46 each object is using the space required for allocCnt unfragmented objects. */
47 SkTLList(int allocCnt = 1) : fCount(0), fAllocCnt(allocCnt) {
48 SkASSERT(allocCnt > 0);
54 typename NodeList::Iter iter;
55 Node* node = iter.init(fList, Iter::kHead_IterStart);
56 while (NULL != node) {
57 SkTCast<T*>(node->fObj)->~T();
58 Block* block = node->fBlock;
60 if (0 == --block->fNodesInUse) {
61 for (int i = 0; i < fAllocCnt; ++i) {
62 block->fNodes[i].~Node();
69 T* addToHead(const T& t) {
71 Node* node = this->createNode();
72 fList.addToHead(node);
73 SkNEW_PLACEMENT_ARGS(node->fObj, T, (t));
75 return reinterpret_cast<T*>(node->fObj);
80 Node* node = this->createNode();
81 fList.addToHead(node);
82 SkNEW_PLACEMENT(node->fObj, T);
84 return reinterpret_cast<T*>(node->fObj);
87 T* addToTail(const T& t) {
89 Node* node = this->createNode();
90 fList.addToTail(node);
91 SkNEW_PLACEMENT_ARGS(node->fObj, T, (t));
93 return reinterpret_cast<T*>(node->fObj);
98 Node* node = this->createNode();
99 fList.addToTail(node);
100 SkNEW_PLACEMENT(node->fObj, T);
102 return reinterpret_cast<T*>(node->fObj);
105 /** Adds a new element to the list before the location indicated by the iterator. If the
106 iterator refers to a NULL location then the new element is added at the tail */
107 T* addBefore(const T& t, const Iter& location) {
108 return SkNEW_PLACEMENT_ARGS(this->internalAddBefore(location), T, (t));
111 /** Adds a new element to the list after the location indicated by the iterator. If the
112 iterator refers to a NULL location then the new element is added at the head */
113 T* addAfter(const T& t, const Iter& location) {
114 return SkNEW_PLACEMENT_ARGS(this->internalAddAfter(location), T, (t));
117 /** Convenience methods for getting an iterator initialized to the head/tail of the list. */
118 Iter headIter() const { return Iter(*this, Iter::kHead_IterStart); }
119 Iter tailIter() const { return Iter(*this, Iter::kTail_IterStart); }
121 T* head() { return Iter(*this, Iter::kHead_IterStart).get(); }
122 T* tail() { return Iter(*this, Iter::kTail_IterStart).get(); }
123 const T* head() const { return Iter(*this, Iter::kHead_IterStart).get(); }
124 const T* tail() const { return Iter(*this, Iter::kTail_IterStart).get(); }
128 Node* node = fList.head();
130 this->removeNode(node);
137 Node* node = fList.head();
139 this->removeNode(node);
146 Node* node = reinterpret_cast<Node*>(t);
147 SkASSERT(reinterpret_cast<T*>(node->fObj) == t);
148 this->removeNode(node);
154 Iter iter(*this, Iter::kHead_IterStart);
158 this->remove(iter.get());
161 SkASSERT(0 == fCount);
165 int count() const { return fCount; }
166 bool isEmpty() const { this->validate(); return 0 == fCount; }
168 bool operator== (const SkTLList& list) const {
172 if (fCount != list.fCount) {
175 for (Iter a(*this, Iter::kHead_IterStart), b(list, Iter::kHead_IterStart);
177 a.next(), b.next()) {
178 SkASSERT(NULL != b.get()); // already checked that counts match.
179 if (!(*a.get() == *b.get())) {
185 bool operator!= (const SkTLList& list) const { return !(*this == list); }
187 /** The iterator becomes invalid if the element it refers to is removed from the list. */
188 class Iter : private NodeList::Iter {
190 typedef typename NodeList::Iter INHERITED;
193 typedef typename INHERITED::IterStart IterStart;
194 //!< Start the iterator at the head of the list.
195 static const IterStart kHead_IterStart = INHERITED::kHead_IterStart;
196 //!< Start the iterator at the tail of the list.
197 static const IterStart kTail_IterStart = INHERITED::kTail_IterStart;
201 Iter(const SkTLList& list, IterStart start) {
202 INHERITED::init(list.fList, start);
205 T* init(const SkTLList& list, IterStart start) {
206 return this->nodeToObj(INHERITED::init(list.fList, start));
209 T* get() { return this->nodeToObj(INHERITED::get()); }
211 T* next() { return this->nodeToObj(INHERITED::next()); }
213 T* prev() { return this->nodeToObj(INHERITED::prev()); }
215 Iter& operator= (const Iter& iter) { INHERITED::operator=(iter); return *this; }
218 friend class SkTLList;
219 Node* getNode() { return INHERITED::get(); }
221 T* nodeToObj(Node* node) {
223 return reinterpret_cast<T*>(node->fObj);
230 // For use with operator new
242 size_t blockSize() const { return sizeof(Block) + sizeof(Node) * (fAllocCnt-1); }
245 Node* node = fFreeList.head();
247 fFreeList.remove(node);
248 ++node->fBlock->fNodesInUse;
250 Block* block = reinterpret_cast<Block*>(sk_malloc_flags(this->blockSize(), 0));
251 node = &block->fNodes[0];
252 SkNEW_PLACEMENT(node, Node);
253 node->fBlock = block;
254 block->fNodesInUse = 1;
255 for (int i = 1; i < fAllocCnt; ++i) {
256 SkNEW_PLACEMENT(block->fNodes + i, Node);
257 fFreeList.addToHead(block->fNodes + i);
258 block->fNodes[i].fBlock = block;
265 void removeNode(Node* node) {
266 SkASSERT(NULL != node);
268 SkTCast<T*>(node->fObj)->~T();
269 if (0 == --node->fBlock->fNodesInUse) {
270 Block* block = node->fBlock;
271 for (int i = 0; i < fAllocCnt; ++i) {
272 if (block->fNodes + i != node) {
273 fFreeList.remove(block->fNodes + i);
275 block->fNodes[i].~Node();
279 fFreeList.addToHead(node);
285 void validate() const {
287 SkASSERT((0 == fCount) == fList.isEmpty());
288 SkASSERT((0 != fCount) || fFreeList.isEmpty());
291 fFreeList.validate();
292 typename NodeList::Iter iter;
293 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart);
295 SkASSERT(fFreeList.isInList(freeNode));
296 Block* block = freeNode->fBlock;
297 SkASSERT(block->fNodesInUse > 0 && block->fNodesInUse < fAllocCnt);
301 for (int i = 0; i < fAllocCnt; ++i) {
302 bool free = fFreeList.isInList(block->fNodes + i);
303 bool active = fList.isInList(block->fNodes + i);
304 SkASSERT(free != active);
308 SkASSERT(activeCnt == block->fNodesInUse);
309 freeNode = iter.next();
313 Node* activeNode = iter.init(fList, Iter::kHead_IterStart);
316 SkASSERT(fList.isInList(activeNode));
317 Block* block = activeNode->fBlock;
318 SkASSERT(block->fNodesInUse > 0 && block->fNodesInUse <= fAllocCnt);
322 for (int i = 0; i < fAllocCnt; ++i) {
323 bool free = fFreeList.isInList(block->fNodes + i);
324 bool active = fList.isInList(block->fNodes + i);
325 SkASSERT(free != active);
329 SkASSERT(activeCnt == block->fNodesInUse);
330 activeNode = iter.next();
332 SkASSERT(count == fCount);
336 // Support in-place initializing of objects inserted into the list via operator new.
337 friend void* operator new<T>(size_t,
340 const Iter& location);
343 // Helpers that insert the node and returns a pointer to where the new object should be init'ed.
344 void* internalAddBefore(Iter location) {
346 Node* node = this->createNode();
347 fList.addBefore(node, location.getNode());
352 void* internalAddAfter(Iter location) {
354 Node* node = this->createNode();
355 fList.addAfter(node, location.getNode());
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(NULL != list);
373 if (SkTLList<T>::kBefore_Placement == placement) {
374 return list->internalAddBefore(location);
376 return list->internalAddAfter(location);
380 // Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete
381 // to match the op new silences warnings about missing op delete when a constructor throws an
383 template <typename T>
384 void operator delete(void*,
386 typename SkTLList<T>::Placement,
387 const typename SkTLList<T>::Iter&) {
391 #define SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args) \
392 (new ((list), SkTLList< type_name >::kBefore_Placement, (location)) type_name args)
394 #define SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args) \
395 (new ((list), SkTLList< type_name >::kAfter_Placement, (location)) type_name args)
397 #define SkNEW_INSERT_AT_LLIST_HEAD(list, type_name, args) \
398 SkNEW_INSERT_IN_LLIST_BEFORE((list), (list)->headIter(), type_name, args)
400 #define SkNEW_INSERT_AT_LLIST_TAIL(list, type_name, args) \
401 SkNEW_INSERT_IN_LLIST_AFTER((list), (list)->tailIter(), type_name, args)