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 "SkTypes.h" 13 #include <utility> 14 15 /** Doubly-linked list of objects. The objects' lifetimes are controlled by the list. I.e. the 16 the list creates the objects and they are deleted upon removal. This class block-allocates 17 space for entries based on a param passed to the constructor. 18 19 Elements of the list can be constructed in place using the following macros: 20 SkNEW_INSERT_IN_LLIST_BEFORE(list, location, type_name, args) 21 SkNEW_INSERT_IN_LLIST_AFTER(list, location, type_name, args) 22 where list is a SkTLList<type_name>*, location is an iterator, and args is the paren-surrounded 23 constructor arguments for type_name. These macros behave like addBefore() and 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. 27 */ 28 template <typename T, unsigned int N> class SkTLList : SkNoncopyable { 29 private: 30 struct Block; 31 struct Node { 32 char fObj[sizeof(T)]; 33 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node); 34 Block* fBlock; // owning block. 35 }; 36 typedef SkTInternalLList<Node> NodeList; 37 38 public: 39 class Iter; 40 SkTLList()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 } 47 this->validate(); 48 } 49 ~SkTLList()50 ~SkTLList() { 51 this->validate(); 52 typename NodeList::Iter iter; 53 Node* node = iter.init(fList, Iter::kHead_IterStart); 54 while (node) { 55 SkTCast<T*>(node->fObj)->~T(); 56 Block* block = node->fBlock; 57 node = iter.next(); 58 if (0 == --block->fNodesInUse) { 59 for (unsigned int i = 0; i < N; ++i) { 60 block->fNodes[i].~Node(); 61 } 62 if (block != &fFirstBlock) { 63 sk_free(block); 64 } 65 } 66 } 67 } 68 69 /** Adds a new element to the list at the head. */ addToHead(Args &&...args)70 template <typename... Args> T* addToHead(Args&&... args) { 71 this->validate(); 72 Node* node = this->createNode(); 73 fList.addToHead(node); 74 this->validate(); 75 return new (node->fObj) T(std::forward<Args>(args)...); 76 } 77 78 /** Adds a new element to the list at the tail. */ addToTail(Args &&...args)79 template <typename... Args> T* addToTail(Args&&... args) { 80 this->validate(); 81 Node* node = this->createNode(); 82 fList.addToTail(node); 83 this->validate(); 84 return new (node->fObj) T(std::forward<Args>(args)...); 85 } 86 87 /** Adds a new element to the list before the location indicated by the iterator. If the 88 iterator refers to a nullptr location then the new element is added at the tail */ addBefore(Iter location,Args &&...args)89 template <typename... Args> T* addBefore(Iter location, Args&&... args) { 90 this->validate(); 91 Node* node = this->createNode(); 92 fList.addBefore(node, location.getNode()); 93 this->validate(); 94 return new (node->fObj) T(std::forward<Args>(args)...); 95 } 96 97 /** Adds a new element to the list after the location indicated by the iterator. If the 98 iterator refers to a nullptr location then the new element is added at the head */ addAfter(Iter location,Args &&...args)99 template <typename... Args> T* addAfter(Iter location, Args&&... args) { 100 this->validate(); 101 Node* node = this->createNode(); 102 fList.addAfter(node, location.getNode()); 103 this->validate(); 104 return new (node->fObj) T(std::forward<Args>(args)...); 105 } 106 107 /** Convenience methods for getting an iterator initialized to the head/tail of the list. */ headIter()108 Iter headIter() const { return Iter(*this, Iter::kHead_IterStart); } tailIter()109 Iter tailIter() const { return Iter(*this, Iter::kTail_IterStart); } 110 head()111 T* head() { return Iter(*this, Iter::kHead_IterStart).get(); } tail()112 T* tail() { return Iter(*this, Iter::kTail_IterStart).get(); } head()113 const T* head() const { return Iter(*this, Iter::kHead_IterStart).get(); } tail()114 const T* tail() const { return Iter(*this, Iter::kTail_IterStart).get(); } 115 popHead()116 void popHead() { 117 this->validate(); 118 Node* node = fList.head(); 119 if (node) { 120 this->removeNode(node); 121 } 122 this->validate(); 123 } 124 popTail()125 void popTail() { 126 this->validate(); 127 Node* node = fList.head(); 128 if (node) { 129 this->removeNode(node); 130 } 131 this->validate(); 132 } 133 remove(T * t)134 void remove(T* t) { 135 this->validate(); 136 Node* node = reinterpret_cast<Node*>(t); 137 SkASSERT(reinterpret_cast<T*>(node->fObj) == t); 138 this->removeNode(node); 139 this->validate(); 140 } 141 reset()142 void reset() { 143 this->validate(); 144 Iter iter(*this, Iter::kHead_IterStart); 145 while (iter.get()) { 146 Iter next = iter; 147 next.next(); 148 this->remove(iter.get()); 149 iter = next; 150 } 151 SkASSERT(0 == fCount); 152 this->validate(); 153 } 154 count()155 int count() const { return fCount; } isEmpty()156 bool isEmpty() const { this->validate(); return 0 == fCount; } 157 158 bool operator== (const SkTLList& list) const { 159 if (this == &list) { 160 return true; 161 } 162 if (fCount != list.fCount) { 163 return false; 164 } 165 for (Iter a(*this, Iter::kHead_IterStart), b(list, Iter::kHead_IterStart); 166 a.get(); 167 a.next(), b.next()) { 168 SkASSERT(b.get()); // already checked that counts match. 169 if (!(*a.get() == *b.get())) { 170 return false; 171 } 172 } 173 return true; 174 } 175 bool operator!= (const SkTLList& list) const { return !(*this == list); } 176 177 /** The iterator becomes invalid if the element it refers to is removed from the list. */ 178 class Iter : private NodeList::Iter { 179 private: 180 typedef typename NodeList::Iter INHERITED; 181 182 public: 183 typedef typename INHERITED::IterStart IterStart; 184 //!< Start the iterator at the head of the list. 185 static const IterStart kHead_IterStart = INHERITED::kHead_IterStart; 186 //!< Start the iterator at the tail of the list. 187 static const IterStart kTail_IterStart = INHERITED::kTail_IterStart; 188 Iter()189 Iter() {} 190 191 Iter(const SkTLList& list, IterStart start = kHead_IterStart) { 192 INHERITED::init(list.fList, start); 193 } 194 195 T* init(const SkTLList& list, IterStart start = kHead_IterStart) { 196 return this->nodeToObj(INHERITED::init(list.fList, start)); 197 } 198 get()199 T* get() { return this->nodeToObj(INHERITED::get()); } 200 next()201 T* next() { return this->nodeToObj(INHERITED::next()); } 202 prev()203 T* prev() { return this->nodeToObj(INHERITED::prev()); } 204 205 Iter& operator= (const Iter& iter) { INHERITED::operator=(iter); return *this; } 206 207 private: 208 friend class SkTLList; getNode()209 Node* getNode() { return INHERITED::get(); } 210 nodeToObj(Node * node)211 T* nodeToObj(Node* node) { 212 if (node) { 213 return reinterpret_cast<T*>(node->fObj); 214 } else { 215 return nullptr; 216 } 217 } 218 }; 219 220 private: 221 struct Block { 222 int fNodesInUse; 223 Node fNodes[N]; 224 }; 225 createNode()226 Node* createNode() { 227 Node* node = fFreeList.head(); 228 if (node) { 229 fFreeList.remove(node); 230 ++node->fBlock->fNodesInUse; 231 } else { 232 // Should not get here when count == 0 because we always have the preallocated first 233 // block. 234 SkASSERT(fCount > 0); 235 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(sizeof(Block))); 236 node = &block->fNodes[0]; 237 new (node) Node; 238 node->fBlock = block; 239 block->fNodesInUse = 1; 240 for (unsigned int i = 1; i < N; ++i) { 241 new (block->fNodes + i) Node; 242 fFreeList.addToHead(block->fNodes + i); 243 block->fNodes[i].fBlock = block; 244 } 245 } 246 ++fCount; 247 return node; 248 } 249 removeNode(Node * node)250 void removeNode(Node* node) { 251 SkASSERT(node); 252 fList.remove(node); 253 SkTCast<T*>(node->fObj)->~T(); 254 Block* block = node->fBlock; 255 // Don't ever elease the first block, just add its nodes to the free list 256 if (0 == --block->fNodesInUse && block != &fFirstBlock) { 257 for (unsigned int i = 0; i < N; ++i) { 258 if (block->fNodes + i != node) { 259 fFreeList.remove(block->fNodes + i); 260 } 261 block->fNodes[i].~Node(); 262 } 263 sk_free(block); 264 } else { 265 fFreeList.addToHead(node); 266 } 267 --fCount; 268 this->validate(); 269 } 270 validate()271 void validate() const { 272 #ifdef SK_DEBUG 273 SkASSERT((0 == fCount) == fList.isEmpty()); 274 if (0 == fCount) { 275 // Should only have the nodes from the first block in the free list. 276 SkASSERT(fFreeList.countEntries() == N); 277 } 278 fList.validate(); 279 fFreeList.validate(); 280 typename NodeList::Iter iter; 281 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart); 282 while (freeNode) { 283 SkASSERT(fFreeList.isInList(freeNode)); 284 Block* block = freeNode->fBlock; 285 // Only the first block is allowed to have all its nodes in the free list. 286 SkASSERT(block->fNodesInUse > 0 || block == &fFirstBlock); 287 SkASSERT((unsigned)block->fNodesInUse < N); 288 int activeCnt = 0; 289 int freeCnt = 0; 290 for (unsigned int i = 0; i < N; ++i) { 291 bool free = fFreeList.isInList(block->fNodes + i); 292 bool active = fList.isInList(block->fNodes + i); 293 SkASSERT(free != active); 294 activeCnt += active; 295 freeCnt += free; 296 } 297 SkASSERT(activeCnt == block->fNodesInUse); 298 freeNode = iter.next(); 299 } 300 301 int count = 0; 302 Node* activeNode = iter.init(fList, Iter::kHead_IterStart); 303 while (activeNode) { 304 ++count; 305 SkASSERT(fList.isInList(activeNode)); 306 Block* block = activeNode->fBlock; 307 SkASSERT(block->fNodesInUse > 0 && (unsigned)block->fNodesInUse <= N); 308 309 int activeCnt = 0; 310 int freeCnt = 0; 311 for (unsigned int i = 0; i < N; ++i) { 312 bool free = fFreeList.isInList(block->fNodes + i); 313 bool active = fList.isInList(block->fNodes + i); 314 SkASSERT(free != active); 315 activeCnt += active; 316 freeCnt += free; 317 } 318 SkASSERT(activeCnt == block->fNodesInUse); 319 activeNode = iter.next(); 320 } 321 SkASSERT(count == fCount); 322 #endif 323 } 324 325 NodeList fList; 326 NodeList fFreeList; 327 Block fFirstBlock; 328 int fCount; 329 }; 330 331 #endif 332