1/*
2 * Copyright 2017 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 SkArenaAllocList_DEFINED
9#define SkArenaAllocList_DEFINED
10
11#include "include/core/SkTypes.h"
12#include "src/core/SkArenaAlloc.h"
13
14/**
15 * A singly linked list of Ts stored in a SkArenaAlloc. The arena rather than the list owns
16 * the elements. This supports forward iteration and range based for loops.
17 */
18template <typename T>
19class SkArenaAllocList {
20private:
21 struct Node;
22
23public:
24 SkArenaAllocList() = default;
25
26 void reset() { fHead = fTail = nullptr; }
27
28 template <typename... Args>
29 inline T& append(SkArenaAlloc* arena, Args... args);
30
31 class Iter {
32 public:
33 Iter() = default;
34 inline Iter& operator++();
35 T& operator*() const { return fCurr->fT; }
36 T* operator->() const { return &fCurr->fT; }
37 bool operator==(const Iter& that) const { return fCurr == that.fCurr; }
38 bool operator!=(const Iter& that) const { return !(*this == that); }
39
40 private:
41 friend class SkArenaAllocList;
42 explicit Iter(Node* node) : fCurr(node) {}
43 Node* fCurr = nullptr;
44 };
45
46 Iter begin() { return Iter(fHead); }
47 Iter end() { return Iter(); }
48 Iter tail() { return Iter(fTail); }
49
50private:
51 struct Node {
52 template <typename... Args>
53 Node(Args... args) : fT(std::forward<Args>(args)...) {}
54 T fT;
55 Node* fNext = nullptr;
56 };
57 Node* fHead = nullptr;
58 Node* fTail = nullptr;
59};
60
61template <typename T>
62template <typename... Args>
63T& SkArenaAllocList<T>::append(SkArenaAlloc* arena, Args... args) {
64 SkASSERT(!fHead == !fTail);
65 auto* n = arena->make<Node>(std::forward<Args>(args)...);
66 if (!fTail) {
67 fHead = fTail = n;
68 } else {
69 fTail = fTail->fNext = n;
70 }
71 return fTail->fT;
72}
73
74template <typename T>
75typename SkArenaAllocList<T>::Iter& SkArenaAllocList<T>::Iter::operator++() {
76 fCurr = fCurr->fNext;
77 return *this;
78}
79
80#endif
81