• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Tint Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef SRC_BLOCK_ALLOCATOR_H_
16 #define SRC_BLOCK_ALLOCATOR_H_
17 
18 #include <memory>
19 #include <utility>
20 #include <vector>
21 
22 namespace tint {
23 
24 /// A container and allocator of objects of (or deriving from) the template type
25 /// `T`.
26 /// Objects are allocated by calling Create(), and are owned by the
27 /// BlockAllocator. When the BlockAllocator is destructed, all constructed
28 /// objects are automatically destructed and freed.
29 ///
30 /// Objects held by the BlockAllocator can be iterated over using a
31 /// View or ConstView.
32 template <typename T>
33 class BlockAllocator {
34   using InternalVector = std::vector<std::unique_ptr<T>>;
35   using InternalIterator = typename InternalVector::const_iterator;
36 
37  public:
38   class View;
39   class ConstView;
40 
41   /// Constructor
42   BlockAllocator() = default;
43   /// Move constructor
44   BlockAllocator(BlockAllocator&&) = default;
45   /// Move assignment operator
46   /// @return this BlockAllocator
47   BlockAllocator& operator=(BlockAllocator&&) = default;
48 
49   /// An iterator for the objects owned by the BlockAllocator.
50   class Iterator {
51    public:
52     /// Equality operator
53     /// @param other the iterator to compare this iterator to
54     /// @returns true if this iterator is equal to other
55     bool operator==(const Iterator& other) const { return it_ == other.it_; }
56     /// Inequality operator
57     /// @param other the iterator to compare this iterator to
58     /// @returns true if this iterator is not equal to other
59     bool operator!=(const Iterator& other) const { return it_ != other.it_; }
60     /// Advances the iterator
61     /// @returns this iterator
62     Iterator& operator++() {
63       ++it_;
64       return *this;
65     }
66     /// @returns the pointer to the object at the current iterator position
67     T* operator*() const { return it_->get(); }
68 
69    private:
70     friend View;  // Keep internal iterator impl private.
Iterator(InternalIterator it)71     explicit Iterator(InternalIterator it) : it_(it) {}
72     InternalIterator it_;
73   };
74 
75   /// A const iterator for the objects owned by the BlockAllocator.
76   class ConstIterator {
77    public:
78     /// Equality operator
79     /// @param other the iterator to compare this iterator to
80     /// @returns true if this iterator is equal to other
81     bool operator==(const ConstIterator& other) const {
82       return it_ == other.it_;
83     }
84     /// Inequality operator
85     /// @param other the iterator to compare this iterator to
86     /// @returns true if this iterator is not equal to other
87     bool operator!=(const ConstIterator& other) const {
88       return it_ != other.it_;
89     }
90     /// Advances the iterator
91     /// @returns this iterator
92     ConstIterator& operator++() {
93       ++it_;
94       return *this;
95     }
96     /// @returns the pointer to the object at the current iterator position
97     T* operator*() const { return it_->get(); }
98 
99    private:
100     friend ConstView;  // Keep internal iterator impl private.
ConstIterator(InternalIterator it)101     explicit ConstIterator(InternalIterator it) : it_(it) {}
102     InternalIterator it_;
103   };
104 
105   /// View provides begin() and end() methods for looping over the objects owned
106   /// by the BlockAllocator.
107   class View {
108    public:
109     /// @returns an iterator to the beginning of the view
begin()110     Iterator begin() const { return Iterator(allocator_->objects_.begin()); }
111     /// @returns an iterator to the end of the view
end()112     Iterator end() const { return Iterator(allocator_->objects_.end()); }
113 
114    private:
115     friend BlockAllocator;  // For BlockAllocator::operator View()
View(BlockAllocator const * allocator)116     explicit View(BlockAllocator const* allocator) : allocator_(allocator) {}
117     BlockAllocator const* const allocator_;
118   };
119 
120   /// ConstView provides begin() and end() methods for looping over the objects
121   /// owned by the BlockAllocator.
122   class ConstView {
123    public:
124     /// @returns an iterator to the beginning of the view
begin()125     ConstIterator begin() const {
126       return ConstIterator(allocator_->objects_.begin());
127     }
128     /// @returns an iterator to the end of the view
end()129     ConstIterator end() const {
130       return ConstIterator(allocator_->objects_.end());
131     }
132 
133    private:
134     friend BlockAllocator;  // For BlockAllocator::operator ConstView()
ConstView(BlockAllocator const * allocator)135     explicit ConstView(BlockAllocator const* allocator)
136         : allocator_(allocator) {}
137     BlockAllocator const* const allocator_;
138   };
139 
140   /// @return a View of all objects owned by this BlockAllocator
Objects()141   View Objects() { return View(this); }
142   /// @return a ConstView of all objects owned by this BlockAllocator
Objects()143   ConstView Objects() const { return ConstView(this); }
144 
145   /// Creates a new `TYPE` owned by the BlockAllocator.
146   /// When the BlockAllocator is destructed the object will be destructed and
147   /// freed.
148   /// @param args the arguments to pass to the type constructor
149   /// @returns the pointer to the constructed object
150   template <typename TYPE = T, typename... ARGS>
Create(ARGS &&...args)151   TYPE* Create(ARGS&&... args) {
152     static_assert(
153         std::is_same<T, TYPE>::value || std::is_base_of<T, TYPE>::value,
154         "TYPE does not derive from T");
155     auto uptr = std::make_unique<TYPE>(std::forward<ARGS>(args)...);
156     auto* ptr = uptr.get();
157     objects_.emplace_back(std::move(uptr));
158     return ptr;
159   }
160 
161  private:
162   BlockAllocator(const BlockAllocator&) = delete;
163   BlockAllocator& operator=(const BlockAllocator&) = delete;
164 
165   std::vector<std::unique_ptr<T>> objects_;
166 };
167 
168 }  // namespace tint
169 
170 #endif  // SRC_BLOCK_ALLOCATOR_H_
171