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