1 /*
2  * Copyright 2018 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 GrCCSTLList_DEFINED
9 #define GrCCSTLList_DEFINED
10 
11 #include "SkArenaAlloc.h"
12 #include "SkNoncopyable.h"
13 #include <new>
14 
15 /**
16  * A singly-linked list whose head element is a local class member. This is required by
17  * GrCCDrawPathsOp because the owning opList is unknown at the time of creation, so we can't use its
18  * associated allocator to create the first element.
19  */
20 template<typename T> class GrCCSTLList : SkNoncopyable {
21 public:
22     template <typename ...Args>
GrCCSTLList(Args &&...args)23     GrCCSTLList(Args&&... args) : fHead(std::forward<Args>(args)...) {}
24 
~GrCCSTLList()25     ~GrCCSTLList() {
26         T* draw = fHead.fNext; // fHead will be destructed automatically.
27         while (draw) {
28             T* next = draw->fNext;
29             draw->~T();
30             draw = next;
31         }
32     }
33 
head()34     const T& head() const { return fHead; }
head()35     T& head() { return fHead; }
36 
append(GrCCSTLList && right,SkArenaAlloc * alloc)37     void append(GrCCSTLList&& right, SkArenaAlloc* alloc) {
38         T* nextTail = (&right.fHead == right.fTail) ? nullptr : right.fTail;
39         T* newRightHead =
40                 new (alloc->makeBytesAlignedTo(sizeof(T), alignof(T))) T(std::move(right.fHead));
41 
42         // Finish the move of right.fHead.
43         right.fHead.fNext = nullptr;
44         right.fTail = &right.fHead;
45 
46         fTail->fNext = newRightHead;
47         fTail = !nextTail ? newRightHead : nextTail;
48     }
49 
50     template<typename U> struct Iter {
51         bool operator!=(const Iter& that) { return fCurr != that.fCurr; }
52         U& operator*() { return *fCurr; }
53         void operator++() { fCurr = fCurr->fNext; }
54         U* fCurr;
55     };
begin()56     Iter<const T> begin() const { return Iter<const T>{&fHead}; }
end()57     Iter<const T> end() const { return Iter<const T>{nullptr}; }
begin()58     Iter<T> begin() { return Iter<T>{&fHead}; }
end()59     Iter<T> end() { return Iter<T>{nullptr}; }
60 
61 private:
62     T fHead;
63     T* fTail = &fHead;
64 };
65 
66 #endif
67