aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/ccpr/GrCCSTLList.h
blob: 3b478e9842bd8af2cfc0d674b99e59ed0ff5c42e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrCCSTLList_DEFINED
#define GrCCSTLList_DEFINED

#include "SkArenaAlloc.h"

/**
 * A singly-linked list whose head element is a local class member. This is required by
 * GrCCDrawPathsOp because the owning opList is unknown at the time of creation, so we can't use its
 * associated allocator to create the first element.
 */
template<typename T> class GrCCSTLList {
public:
    GrCCSTLList(T&& head) : fHead(std::move(head)) {}

    ~GrCCSTLList() {
        T* draw = fHead.fNext; // fHead will be destructed automatically.
        while (draw) {
            T* next = draw->fNext;
            draw->~T();
            draw = next;
        }
    }

    const T& head() const { return fHead; }
    T& head() { return fHead; }

    void append(GrCCSTLList&& right, SkArenaAlloc* alloc) {
        T* nextTail = (&right.fHead == right.fTail) ? nullptr : right.fTail;
        T* newRightHead =
                new (alloc->makeBytesAlignedTo(sizeof(T), alignof(T))) T(std::move(right.fHead));

        // Finish the move of right.fHead.
        right.fHead.fNext = nullptr;
        right.fTail = &right.fHead;

        fTail->fNext = newRightHead;
        fTail = !nextTail ? newRightHead : nextTail;
    }

    struct Iter {
        bool operator!=(const Iter& that) { return fCurr != that.fCurr; }
        const T& operator*() { return *fCurr; }
        void operator++() { fCurr = fCurr->fNext; }
        const T* fCurr;
    };
    Iter begin() const { return Iter{&fHead}; }
    Iter end() const { return Iter{nullptr}; }

private:
    T fHead;
    T* fTail = &fHead;
};

#endif