diff options
Diffstat (limited to 'src/core/SkArenaAllocList.h')
-rw-r--r-- | src/core/SkArenaAllocList.h | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/src/core/SkArenaAllocList.h b/src/core/SkArenaAllocList.h new file mode 100644 index 0000000000..b4e442b0bd --- /dev/null +++ b/src/core/SkArenaAllocList.h @@ -0,0 +1,79 @@ +/* + * Copyright 2017 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef SkArenaAllocList_DEFINED +#define SkArenaAllocList_DEFINED + +#include "SkArenaAlloc.h" + +/** + * A singly linked list of Ts stored in a SkArenaAlloc. The arena rather than the list owns + * the elements. This supports forward iteration and range based for loops. + */ +template <typename T> +class SkArenaAllocList { +private: + struct Node; + +public: + SkArenaAllocList() = default; + + void reset() { fHead = fTail = nullptr; } + + template <typename... Args> + inline T& append(SkArenaAlloc* arena, Args... args); + + class Iter { + public: + Iter() = default; + inline Iter& operator++(); + T& operator*() const { return fCurr->fT; } + T* operator->() const { return &fCurr->fT; } + bool operator==(const Iter& that) const { return fCurr == that.fCurr; } + bool operator!=(const Iter& that) const { return !(*this == that); } + + private: + friend class SkArenaAllocList; + explicit Iter(Node* node) : fCurr(node) {} + Node* fCurr = nullptr; + }; + + Iter begin() { return Iter(fHead); } + Iter end() { return Iter(); } + Iter tail() { return Iter(fTail); } + +private: + struct Node { + template <typename... Args> + Node(Args... args) : fT(std::forward<Args>(args)...) {} + T fT; + Node* fNext = nullptr; + }; + Node* fHead = nullptr; + Node* fTail = nullptr; +}; + +template <typename T> +template <typename... Args> +T& SkArenaAllocList<T>::append(SkArenaAlloc* arena, Args... args) { + SkASSERT(!fHead == !fTail); + auto* n = arena->make<Node>(std::forward<Args>(args)...); + if (!fTail) { + fHead = fTail = n; + } else { + fTail = fTail->fNext = n; + } + return fTail->fT; +} + +template <typename T> +typename SkArenaAllocList<T>::Iter& SkArenaAllocList<T>::Iter::operator++() { + fCurr = fCurr->fNext; + return *this; +} + +#endif |