| /* |
| * Copyright 2014 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef SkTInternalSList_DEFINED |
| #define SkTInternalSList_DEFINED |
| |
| #include "SkTInternalLList.h" // for SkPtrWrapper |
| |
| /** |
| * This macro creates the methods required by the SkTInternalSList class. |
| * It should be instantiated in the private block of the class you want to put |
| * into an SkTInternalSList. |
| * For most use cases you should use SK_DECLARE_INTERNAL_SLIST_INTERFACE and not |
| * this macro. If you care about the field name, or want to re-use an existing |
| * field, then you can use this macro to declare the methods pointing to a |
| * specific field. |
| * Unlike SK_DECLARE_INTERNAL_SLIST_INTERFACE this does not declare the field |
| * itself. |
| * It also makes SkTInternalSList<ClassName> a friend to give it access to the |
| * methods. |
| */ |
| #define SK_DECLARE_INTERNAL_SLIST_ADAPTER(ClassName, field) \ |
| ClassName* getSListNext() { \ |
| return this->field; \ |
| } \ |
| void setSListNext(ClassName* next) { \ |
| this->field = next; \ |
| } \ |
| friend class SkTInternalSList<ClassName> |
| |
| /** |
| * This macro declares an fSListNext that auto initializes to NULL and then |
| * uses SK_DECLARE_INTERNAL_SLIST_ADAPTER to add the methods needed by |
| * SkTInternalSList. |
| * It should be instantiated in the private block of the class you want to put |
| * into an SkTInternalSList. |
| */ |
| #define SK_DECLARE_INTERNAL_SLIST_INTERFACE(ClassName) \ |
| SK_DECLARE_INTERNAL_SLIST_ADAPTER(ClassName, fSListNext); \ |
| SkPtrWrapper<ClassName> fSListNext |
| |
| /** |
| * An implementation of an intrusive singly linked list. |
| * The type T must have a methods getSListNext and setSListNext that are visible |
| * to the list. The easiest way to do this is with |
| * SK_DECLARE_INTERNAL_SLIST_INTERFACE. |
| * The list does not maintain ownership of any of its elements, or ever delete |
| * them. |
| */ |
| template<typename T> class SkTInternalSList { |
| public: |
| SkTInternalSList() : fHead(NULL), fCount(0) {} |
| |
| /** |
| * Push an item onto the head of the list. |
| * This method is *not* thread safe. |
| */ |
| void push(T* entry) { |
| SkASSERT(entry->getSListNext() == NULL); |
| entry->setSListNext(fHead); |
| fHead = entry; |
| ++fCount; |
| } |
| |
| /** |
| * Takes all the items from another list and pushes them into this list. |
| * No ordering guarantees are made, the other list will be emptied. |
| * This method is *not* thread safe. |
| */ |
| void pushAll(SkTInternalSList<T>* other) { |
| if (this->isEmpty()) { |
| this->swap(other); |
| return; |
| } |
| while (!other->isEmpty()) { |
| this->push(other->pop()); |
| } |
| } |
| |
| /** |
| * Pop an item from the head of the list. |
| * Returns NULL if the list is empty. |
| * This method is *not* thread safe. |
| */ |
| T* pop() { |
| if (NULL == fHead) { |
| return NULL; |
| } |
| T* result = fHead; |
| fHead = result->getSListNext(); |
| result->setSListNext(NULL); |
| --fCount; |
| return result; |
| } |
| |
| T* head() const { |
| return fHead; |
| } |
| |
| /** |
| * Returns true if the list has no elements. |
| */ |
| bool isEmpty() const { |
| return NULL == fHead; |
| } |
| |
| /** |
| * Swaps the contents of this list with another one. |
| * This method is *not* thread safe. |
| */ |
| void swap(SkTInternalSList<T>* other) { |
| SkTSwap(fHead, other->fHead); |
| SkTSwap(fCount, other->fCount); |
| } |
| |
| /** |
| * Returns the count of elements in the list. |
| */ |
| int getCount() const { |
| return fCount; |
| } |
| private: |
| T* fHead; |
| int fCount; |
| }; |
| |
| |
| #endif |