| 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 |
| (...skipping 20 matching lines...) Expand all Loading... |
| 31 struct Node { | 31 struct Node { |
| 32 char fObj[sizeof(T)]; | 32 char fObj[sizeof(T)]; |
| 33 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node); | 33 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Node); |
| 34 Block* fBlock; // owning block. | 34 Block* fBlock; // owning block. |
| 35 }; | 35 }; |
| 36 typedef SkTInternalLList<Node> NodeList; | 36 typedef SkTInternalLList<Node> NodeList; |
| 37 | 37 |
| 38 public: | 38 public: |
| 39 class Iter; | 39 class Iter; |
| 40 | 40 |
| 41 SkTLList() : fCount(0) { | 41 // Having fCount initialized to -1 indicates that the first time we attempt
to grab a free node |
| 42 fFirstBlock.fNodesInUse = 0; | 42 // all the nodes in the pre-allocated first block need to be inserted into t
he free list. This |
| 43 for (unsigned int i = 0; i < N; ++i) { | 43 // allows us to skip that loop in instances when the list is never populated
. |
| 44 fFreeList.addToHead(fFirstBlock.fNodes + i); | 44 SkTLList() : fCount(-1) {} |
| 45 fFirstBlock.fNodes[i].fBlock = &fFirstBlock; | |
| 46 } | |
| 47 this->validate(); | |
| 48 } | |
| 49 | 45 |
| 50 ~SkTLList() { | 46 ~SkTLList() { |
| 51 this->validate(); | 47 this->validate(); |
| 52 typename NodeList::Iter iter; | 48 typename NodeList::Iter iter; |
| 53 Node* node = iter.init(fList, Iter::kHead_IterStart); | 49 Node* node = iter.init(fList, Iter::kHead_IterStart); |
| 54 while (node) { | 50 while (node) { |
| 55 SkTCast<T*>(node->fObj)->~T(); | 51 SkTCast<T*>(node->fObj)->~T(); |
| 56 Block* block = node->fBlock; | 52 Block* block = node->fBlock; |
| 57 node = iter.next(); | 53 node = iter.next(); |
| 58 if (0 == --block->fNodesInUse) { | 54 if (0 == --block->fNodesInUse) { |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 141 | 137 |
| 142 void reset() { | 138 void reset() { |
| 143 this->validate(); | 139 this->validate(); |
| 144 Iter iter(*this, Iter::kHead_IterStart); | 140 Iter iter(*this, Iter::kHead_IterStart); |
| 145 while (iter.get()) { | 141 while (iter.get()) { |
| 146 Iter next = iter; | 142 Iter next = iter; |
| 147 next.next(); | 143 next.next(); |
| 148 this->remove(iter.get()); | 144 this->remove(iter.get()); |
| 149 iter = next; | 145 iter = next; |
| 150 } | 146 } |
| 151 SkASSERT(0 == fCount); | 147 SkASSERT(0 == fCount || -1 == fCount); |
| 152 this->validate(); | 148 this->validate(); |
| 153 } | 149 } |
| 154 | 150 |
| 155 int count() const { return fCount; } | 151 int count() const { return SkTMax(fCount ,0); } |
| 156 bool isEmpty() const { this->validate(); return 0 == fCount; } | 152 bool isEmpty() const { this->validate(); return 0 == fCount || -1 == fCount;
} |
| 157 | 153 |
| 158 bool operator== (const SkTLList& list) const { | 154 bool operator== (const SkTLList& list) const { |
| 159 if (this == &list) { | 155 if (this == &list) { |
| 160 return true; | 156 return true; |
| 161 } | 157 } |
| 162 if (fCount != list.fCount) { | 158 // Call count() rather than use fCount because an empty list may have fC
ount = 0 or -1. |
| 159 if (this->count() != list.count()) { |
| 163 return false; | 160 return false; |
| 164 } | 161 } |
| 165 for (Iter a(*this, Iter::kHead_IterStart), b(list, Iter::kHead_IterStart
); | 162 for (Iter a(*this, Iter::kHead_IterStart), b(list, Iter::kHead_IterStart
); |
| 166 a.get(); | 163 a.get(); |
| 167 a.next(), b.next()) { | 164 a.next(), b.next()) { |
| 168 SkASSERT(b.get()); // already checked that counts match. | 165 SkASSERT(b.get()); // already checked that counts match. |
| 169 if (!(*a.get() == *b.get())) { | 166 if (!(*a.get() == *b.get())) { |
| 170 return false; | 167 return false; |
| 171 } | 168 } |
| 172 } | 169 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 216 } | 213 } |
| 217 } | 214 } |
| 218 }; | 215 }; |
| 219 | 216 |
| 220 private: | 217 private: |
| 221 struct Block { | 218 struct Block { |
| 222 int fNodesInUse; | 219 int fNodesInUse; |
| 223 Node fNodes[N]; | 220 Node fNodes[N]; |
| 224 }; | 221 }; |
| 225 | 222 |
| 223 void delayedInit() { |
| 224 SkASSERT(-1 == fCount); |
| 225 fFirstBlock.fNodesInUse = 0; |
| 226 for (unsigned int i = 0; i < N; ++i) { |
| 227 fFreeList.addToHead(fFirstBlock.fNodes + i); |
| 228 fFirstBlock.fNodes[i].fBlock = &fFirstBlock; |
| 229 } |
| 230 fCount = 0; |
| 231 this->validate(); |
| 232 } |
| 233 |
| 226 Node* createNode() { | 234 Node* createNode() { |
| 235 if (-1 == fCount) { |
| 236 this->delayedInit(); |
| 237 } |
| 227 Node* node = fFreeList.head(); | 238 Node* node = fFreeList.head(); |
| 228 if (node) { | 239 if (node) { |
| 229 fFreeList.remove(node); | 240 fFreeList.remove(node); |
| 230 ++node->fBlock->fNodesInUse; | 241 ++node->fBlock->fNodesInUse; |
| 231 } else { | 242 } else { |
| 232 // Should not get here when count == 0 because we always have the pr
eallocated first | 243 // Should not get here when count == 0 because we always have the pr
eallocated first |
| 233 // block. | 244 // block. |
| 234 SkASSERT(fCount > 0); | 245 SkASSERT(fCount > 0); |
| 235 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(sizeof(Block
))); | 246 Block* block = reinterpret_cast<Block*>(sk_malloc_throw(sizeof(Block
))); |
| 236 node = &block->fNodes[0]; | 247 node = &block->fNodes[0]; |
| (...skipping 26 matching lines...) Expand all Loading... |
| 263 sk_free(block); | 274 sk_free(block); |
| 264 } else { | 275 } else { |
| 265 fFreeList.addToHead(node); | 276 fFreeList.addToHead(node); |
| 266 } | 277 } |
| 267 --fCount; | 278 --fCount; |
| 268 this->validate(); | 279 this->validate(); |
| 269 } | 280 } |
| 270 | 281 |
| 271 void validate() const { | 282 void validate() const { |
| 272 #ifdef SK_DEBUG | 283 #ifdef SK_DEBUG |
| 273 SkASSERT((0 == fCount) == fList.isEmpty()); | 284 bool isEmpty = false; |
| 274 if (0 == fCount) { | 285 if (-1 == fCount) { |
| 286 // We should not yet have initialized the free list. |
| 287 SkASSERT(fFreeList.isEmpty()); |
| 288 isEmpty = true; |
| 289 } else if (0 == fCount) { |
| 275 // Should only have the nodes from the first block in the free list. | 290 // Should only have the nodes from the first block in the free list. |
| 276 SkASSERT(fFreeList.countEntries() == N); | 291 SkASSERT(fFreeList.countEntries() == N); |
| 292 isEmpty = true; |
| 277 } | 293 } |
| 294 SkASSERT(isEmpty == fList.isEmpty()); |
| 278 fList.validate(); | 295 fList.validate(); |
| 279 fFreeList.validate(); | 296 fFreeList.validate(); |
| 280 typename NodeList::Iter iter; | 297 typename NodeList::Iter iter; |
| 281 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart); | 298 Node* freeNode = iter.init(fFreeList, Iter::kHead_IterStart); |
| 282 while (freeNode) { | 299 while (freeNode) { |
| 283 SkASSERT(fFreeList.isInList(freeNode)); | 300 SkASSERT(fFreeList.isInList(freeNode)); |
| 284 Block* block = freeNode->fBlock; | 301 Block* block = freeNode->fBlock; |
| 285 // Only the first block is allowed to have all its nodes in the free
list. | 302 // Only the first block is allowed to have all its nodes in the free
list. |
| 286 SkASSERT(block->fNodesInUse > 0 || block == &fFirstBlock); | 303 SkASSERT(block->fNodesInUse > 0 || block == &fFirstBlock); |
| 287 SkASSERT((unsigned)block->fNodesInUse < N); | 304 SkASSERT((unsigned)block->fNodesInUse < N); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 311 for (unsigned int i = 0; i < N; ++i) { | 328 for (unsigned int i = 0; i < N; ++i) { |
| 312 bool free = fFreeList.isInList(block->fNodes + i); | 329 bool free = fFreeList.isInList(block->fNodes + i); |
| 313 bool active = fList.isInList(block->fNodes + i); | 330 bool active = fList.isInList(block->fNodes + i); |
| 314 SkASSERT(free != active); | 331 SkASSERT(free != active); |
| 315 activeCnt += active; | 332 activeCnt += active; |
| 316 freeCnt += free; | 333 freeCnt += free; |
| 317 } | 334 } |
| 318 SkASSERT(activeCnt == block->fNodesInUse); | 335 SkASSERT(activeCnt == block->fNodesInUse); |
| 319 activeNode = iter.next(); | 336 activeNode = iter.next(); |
| 320 } | 337 } |
| 321 SkASSERT(count == fCount); | 338 SkASSERT(count == fCount || (0 == count && -1 == fCount)); |
| 322 #endif | 339 #endif |
| 323 } | 340 } |
| 324 | 341 |
| 325 NodeList fList; | 342 NodeList fList; |
| 326 NodeList fFreeList; | 343 NodeList fFreeList; |
| 327 Block fFirstBlock; | 344 Block fFirstBlock; |
| 328 int fCount; | 345 int fCount; |
| 329 }; | 346 }; |
| 330 | 347 |
| 331 #endif | 348 #endif |
| OLD | NEW |