171 lines
5.8 KiB
C++
171 lines
5.8 KiB
C++
// Copyright 2021 The Tint Authors.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
#ifndef SRC_BLOCK_ALLOCATOR_H_
|
|
#define SRC_BLOCK_ALLOCATOR_H_
|
|
|
|
#include <memory>
|
|
#include <utility>
|
|
#include <vector>
|
|
|
|
namespace tint {
|
|
|
|
/// A container and allocator of objects of (or deriving from) the template type
|
|
/// `T`.
|
|
/// Objects are allocated by calling Create(), and are owned by the
|
|
/// BlockAllocator. When the BlockAllocator is destructed, all constructed
|
|
/// objects are automatically destructed and freed.
|
|
///
|
|
/// Objects held by the BlockAllocator can be iterated over using a
|
|
/// View or ConstView.
|
|
template <typename T>
|
|
class BlockAllocator {
|
|
using InternalVector = std::vector<std::unique_ptr<T>>;
|
|
using InternalIterator = typename InternalVector::const_iterator;
|
|
|
|
public:
|
|
class View;
|
|
class ConstView;
|
|
|
|
/// Constructor
|
|
BlockAllocator() = default;
|
|
/// Move constructor
|
|
BlockAllocator(BlockAllocator&&) = default;
|
|
/// Move assignment operator
|
|
/// @return this BlockAllocator
|
|
BlockAllocator& operator=(BlockAllocator&&) = default;
|
|
|
|
/// An iterator for the objects owned by the BlockAllocator.
|
|
class Iterator {
|
|
public:
|
|
/// Equality operator
|
|
/// @param other the iterator to compare this iterator to
|
|
/// @returns true if this iterator is equal to other
|
|
bool operator==(const Iterator& other) const { return it_ == other.it_; }
|
|
/// Inequality operator
|
|
/// @param other the iterator to compare this iterator to
|
|
/// @returns true if this iterator is not equal to other
|
|
bool operator!=(const Iterator& other) const { return it_ != other.it_; }
|
|
/// Advances the iterator
|
|
/// @returns this iterator
|
|
Iterator& operator++() {
|
|
++it_;
|
|
return *this;
|
|
}
|
|
/// @returns the pointer to the object at the current iterator position
|
|
T* operator*() const { return it_->get(); }
|
|
|
|
private:
|
|
friend View; // Keep internal iterator impl private.
|
|
explicit Iterator(InternalIterator it) : it_(it) {}
|
|
InternalIterator it_;
|
|
};
|
|
|
|
/// A const iterator for the objects owned by the BlockAllocator.
|
|
class ConstIterator {
|
|
public:
|
|
/// Equality operator
|
|
/// @param other the iterator to compare this iterator to
|
|
/// @returns true if this iterator is equal to other
|
|
bool operator==(const ConstIterator& other) const {
|
|
return it_ == other.it_;
|
|
}
|
|
/// Inequality operator
|
|
/// @param other the iterator to compare this iterator to
|
|
/// @returns true if this iterator is not equal to other
|
|
bool operator!=(const ConstIterator& other) const {
|
|
return it_ != other.it_;
|
|
}
|
|
/// Advances the iterator
|
|
/// @returns this iterator
|
|
ConstIterator& operator++() {
|
|
++it_;
|
|
return *this;
|
|
}
|
|
/// @returns the pointer to the object at the current iterator position
|
|
T* operator*() const { return it_->get(); }
|
|
|
|
private:
|
|
friend ConstView; // Keep internal iterator impl private.
|
|
explicit ConstIterator(InternalIterator it) : it_(it) {}
|
|
InternalIterator it_;
|
|
};
|
|
|
|
/// View provides begin() and end() methods for looping over the objects owned
|
|
/// by the BlockAllocator.
|
|
class View {
|
|
public:
|
|
/// @returns an iterator to the beginning of the view
|
|
Iterator begin() const { return Iterator(allocator_->objects_.begin()); }
|
|
/// @returns an iterator to the end of the view
|
|
Iterator end() const { return Iterator(allocator_->objects_.end()); }
|
|
|
|
private:
|
|
friend BlockAllocator; // For BlockAllocator::operator View()
|
|
explicit View(BlockAllocator const* allocator) : allocator_(allocator) {}
|
|
BlockAllocator const* const allocator_;
|
|
};
|
|
|
|
/// ConstView provides begin() and end() methods for looping over the objects
|
|
/// owned by the BlockAllocator.
|
|
class ConstView {
|
|
public:
|
|
/// @returns an iterator to the beginning of the view
|
|
ConstIterator begin() const {
|
|
return ConstIterator(allocator_->objects_.begin());
|
|
}
|
|
/// @returns an iterator to the end of the view
|
|
ConstIterator end() const {
|
|
return ConstIterator(allocator_->objects_.end());
|
|
}
|
|
|
|
private:
|
|
friend BlockAllocator; // For BlockAllocator::operator ConstView()
|
|
explicit ConstView(BlockAllocator const* allocator)
|
|
: allocator_(allocator) {}
|
|
BlockAllocator const* const allocator_;
|
|
};
|
|
|
|
/// @return a View of all objects owned by this BlockAllocator
|
|
View Objects() { return View(this); }
|
|
/// @return a ConstView of all objects owned by this BlockAllocator
|
|
ConstView Objects() const { return ConstView(this); }
|
|
|
|
/// Creates a new `TYPE` owned by the BlockAllocator.
|
|
/// When the BlockAllocator is destructed the object will be destructed and
|
|
/// freed.
|
|
/// @param args the arguments to pass to the type constructor
|
|
/// @returns the pointer to the constructed object
|
|
template <typename TYPE = T, typename... ARGS>
|
|
TYPE* Create(ARGS&&... args) {
|
|
static_assert(
|
|
std::is_same<T, TYPE>::value || std::is_base_of<T, TYPE>::value,
|
|
"TYPE does not derive from T");
|
|
auto uptr = std::make_unique<TYPE>(std::forward<ARGS>(args)...);
|
|
auto ptr = uptr.get();
|
|
objects_.emplace_back(std::move(uptr));
|
|
return ptr;
|
|
}
|
|
|
|
private:
|
|
BlockAllocator(const BlockAllocator&) = delete;
|
|
BlockAllocator& operator=(const BlockAllocator&) = delete;
|
|
|
|
std::vector<std::unique_ptr<T>> objects_;
|
|
};
|
|
|
|
} // namespace tint
|
|
|
|
#endif // SRC_BLOCK_ALLOCATOR_H_
|