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 "include/private/SkNoncopyable.h"
12#include "src/core/SkArenaAlloc.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 opsTask is unknown at the time of creation, so we can't use
18 * its associated allocator to create the first element.
19 */
20template<typename T> class GrCCSTLList : SkNoncopyable {
21public:
22 template <typename ...Args>
23 GrCCSTLList(Args&&... args) : fHead(std::forward<Args>(args)...) {}
24
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
34 const T& head() const { return fHead; }
35 T& head() { return fHead; }
36
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 };
56 Iter<const T> begin() const { return Iter<const T>{&fHead}; }
57 Iter<const T> end() const { return Iter<const T>{nullptr}; }
58 Iter<T> begin() { return Iter<T>{&fHead}; }
59 Iter<T> end() { return Iter<T>{nullptr}; }
60
61private:
62 T fHead;
63 T* fTail = &fHead;
64};
65
66#endif
67