1 /*
2  * Copyright 2012 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef SkTLList_DEFINED
9 #define SkTLList_DEFINED
10 
11 #include "SkTInternalLList.h"
12 #include "SkTemplates.h"
13 
14 template <typename T> class SkTLList;
15 template <typename T>
16 inline void* operator new(size_t, SkTLList<T>* list,
17                           typename SkTLList<T>::Placement placement,
18                           const typename SkTLList<T>::Iter& location);
19 
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.
23 
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().
29 */
30 template <typename T>
31 class SkTLList : SkNoncopyable {
32 private:
33     struct Block;
34     struct Node {
35         char fObj[sizeof(T)];
36         SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node);
37         Block* fBlock; // owning block.
38     };
39     typedef SkTInternalLList<Node> NodeList;
40 
41 public:
42 
43     class Iter;
44 
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);
49         this->validate();
50     }
51 
~SkTLList()52     ~SkTLList() {
53         this->validate();
54         typename NodeList::Iter iter;
55         Node* node = iter.init(fList, Iter::kHead_IterStart);
56         while (node) {
57             SkTCast<T*>(node->fObj)->~T();
58             Block* block = node->fBlock;
59             node = iter.next();
60             if (0 == --block->fNodesInUse) {
61                 for (int i = 0; i < fAllocCnt; ++i) {
62                     block->fNodes[i].~Node();
63                 }
64                 sk_free(block);
65             }
66         }
67     }
68 
addToHead(const T & t)69     T* addToHead(const T& t) {
70         this->validate();
71         Node* node = this->createNode();
72         fList.addToHead(node);
73         SkNEW_PLACEMENT_ARGS(node->fObj, T, (t));
74         this->validate();
75         return reinterpret_cast<T*>(node->fObj);
76     }
77 
addToHead()78     T* addToHead() {
79         this->validate();
80         Node* node = this->createNode();
81         fList.addToHead(node);
82         SkNEW_PLACEMENT(node->fObj, T);
83         this->validate();
84         return reinterpret_cast<T*>(node->fObj);
85     }
86 
addToTail(const T & t)87     T* addToTail(const T& t) {
88         this->validate();
89         Node* node = this->createNode();
90         fList.addToTail(node);
91         SkNEW_PLACEMENT_ARGS(node->fObj, T, (t));
92         this->validate();
93         return reinterpret_cast<T*>(node->fObj);
94     }
95 
addToTail()96     T* addToTail() {
97         this->validate();
98         Node* node = this->createNode();
99         fList.addToTail(node);
100         SkNEW_PLACEMENT(node->fObj, T);
101         this->validate();
102         return reinterpret_cast<T*>(node->fObj);
103     }
104 
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 */
addBefore(const T & t,const Iter & location)107     T* addBefore(const T& t, const Iter& location) {
108         return SkNEW_PLACEMENT_ARGS(this->internalAddBefore(location), T, (t));
109     }
110 
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 */
addAfter(const T & t,const Iter & location)113     T* addAfter(const T& t, const Iter& location) {
114         return SkNEW_PLACEMENT_ARGS(this->internalAddAfter(location), T, (t));
115     }
116 
117     /** Convenience methods for getting an iterator initialized to the head/tail of the list. */
headIter()118     Iter headIter() const { return Iter(*this, Iter::kHead_IterStart); }
tailIter()119     Iter tailIter() const { return Iter(*this, Iter::kTail_IterStart); }
120 
head()121     T* head() { return Iter(*this, Iter::kHead_IterStart).get(); }
tail()122     T* tail() { return Iter(*this, Iter::kTail_IterStart).get(); }
head()123     const T* head() const { return Iter(*this, Iter::kHead_IterStart).get(); }
tail()124     const T* tail() const { return Iter(*this, Iter::kTail_IterStart).get(); }
125 
popHead()126     void popHead() {
127         this->validate();
128         Node* node = fList.head();
129         if (node) {
130             this->removeNode(node);
131         }
132         this->validate();
133     }
134 
popTail()135     void popTail() {
136         this->validate();
137         Node* node = fList.head();
138         if (node) {
139             this->removeNode(node);
140         }
141         this->validate();
142     }
143 
remove(T * t)144     void remove(T* t) {
145         this->validate();
146         Node* node = reinterpret_cast<Node*>(t);
147         SkASSERT(reinterpret_cast<T*>(node->fObj) == t);
148         this->removeNode(node);
149         this->validate();
150     }
151 
reset()152     void reset() {
153         this->validate();
154         Iter iter(*this, Iter::kHead_IterStart);
155         while (iter.get()) {
156             Iter next = iter;
157             next.next();
158             this->remove(iter.get());
159             iter = next;
160         }
161         SkASSERT(0 == fCount);
162         this->validate();
163     }
164 
count()165     int count() const { return fCount; }
isEmpty()166     bool isEmpty() const { this->validate(); return 0 == fCount; }
167 
168     bool operator== (const SkTLList& list) const {
169         if (this == &list) {
170             return true;
171         }
172         if (fCount != list.fCount) {
173             return false;
174         }
175         for (Iter a(*this, Iter::kHead_IterStart), b(list, Iter::kHead_IterStart);
176              a.get();
177              a.next(), b.next()) {
178             SkASSERT(b.get()); // already checked that counts match.
179             if (!(*a.get() == *b.get())) {
180                 return false;
181             }
182         }
183         return true;
184     }
185     bool operator!= (const SkTLList& list) const { return !(*this == list); }
186 
187     /** The iterator becomes invalid if the element it refers to is removed from the list. */
188     class Iter : private NodeList::Iter {
189     private:
190         typedef typename NodeList::Iter INHERITED;
191 
192     public:
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;
198 
Iter()199         Iter() {}
200 
201         Iter(const SkTLList& list, IterStart start = kHead_IterStart) {
202             INHERITED::init(list.fList, start);
203         }
204 
205         T* init(const SkTLList& list, IterStart start = kHead_IterStart) {
206             return this->nodeToObj(INHERITED::init(list.fList, start));
207         }
208 
get()209         T* get() { return this->nodeToObj(INHERITED::get()); }
210 
next()211         T* next() { return this->nodeToObj(INHERITED::next()); }
212 
prev()213         T* prev() { return this->nodeToObj(INHERITED::prev()); }
214 
215         Iter& operator= (const Iter& iter) { INHERITED::operator=(iter); return *this; }
216 
217     private:
218         friend class SkTLList;
getNode()219         Node* getNode() { return INHERITED::get(); }
220 
nodeToObj(Node * node)221         T* nodeToObj(Node* node) {
222             if (node) {
223                 return reinterpret_cast<T*>(node->fObj);
224             } else {
225                 return NULL;
226             }
227         }
228     };
229 
230     // For use with operator new
231     enum Placement {
232         kBefore_Placement,
233         kAfter_Placement,
234     };
235 
236 private:
237     struct Block {
238         int fNodesInUse;
239         Node fNodes[1];
240     };
241 
blockSize()242     size_t blockSize() const { return sizeof(Block) + sizeof(Node) * (fAllocCnt-1); }
243 
createNode()244     Node* createNode() {
245         Node* node = fFreeList.head();
246         if (node) {
247             fFreeList.remove(node);
248             ++node->fBlock->fNodesInUse;
249         } else {
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;
259             }
260         }
261         ++fCount;
262         return node;
263     }
264 
removeNode(Node * node)265     void removeNode(Node* node) {
266         SkASSERT(node);
267         fList.remove(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);
274                 }
275                 block->fNodes[i].~Node();
276             }
277             sk_free(block);
278         } else {
279             fFreeList.addToHead(node);
280         }
281         --fCount;
282         this->validate();
283     }
284 
validate()285     void validate() const {
286 #ifdef SK_DEBUG
287         SkASSERT((0 == fCount) == fList.isEmpty());
288         SkASSERT((0 != fCount) || fFreeList.isEmpty());
289 
290         fList.validate();
291         fFreeList.validate();
292         typename NodeList::Iter iter;
293         Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart);
294         while (freeNode) {
295             SkASSERT(fFreeList.isInList(freeNode));
296             Block* block = freeNode->fBlock;
297             SkASSERT(block->fNodesInUse > 0 && block->fNodesInUse < fAllocCnt);
298 
299             int activeCnt = 0;
300             int freeCnt = 0;
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);
305                 activeCnt += active;
306                 freeCnt += free;
307             }
308             SkASSERT(activeCnt == block->fNodesInUse);
309             freeNode = iter.next();
310         }
311 
312         int count = 0;
313         Node* activeNode = iter.init(fList, Iter::kHead_IterStart);
314         while (activeNode) {
315             ++count;
316             SkASSERT(fList.isInList(activeNode));
317             Block* block = activeNode->fBlock;
318             SkASSERT(block->fNodesInUse > 0 && block->fNodesInUse <= fAllocCnt);
319 
320             int activeCnt = 0;
321             int freeCnt = 0;
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);
326                 activeCnt += active;
327                 freeCnt += free;
328             }
329             SkASSERT(activeCnt == block->fNodesInUse);
330             activeNode = iter.next();
331         }
332         SkASSERT(count == fCount);
333 #endif
334     }
335 
336     // Support in-place initializing of objects inserted into the list via operator 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 object should be init'ed.
internalAddBefore(Iter location)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 
internalAddAfter(Iter location)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;
361     NodeList fFreeList;
362     int fCount;
363     int fAllocCnt;
364 
365 };
366 
367 // Use the below macros rather than calling this directly
368 template <typename T>
new(size_t,SkTLList<T> * list,typename SkTLList<T>::Placement placement,const typename SkTLList<T>::Iter & location)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. Having an op delete
381 // to match the op new silences warnings about missing op delete when a constructor throws an
382 // exception.
383 template <typename T>
delete(void *,SkTLList<T> *,typename SkTLList<T>::Placement,const typename SkTLList<T>::Iter &)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_name 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
404