| 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 |