Move allocator into TypeManager
Currently the TypeManger is a UniqueAllocator. This works as long as the
TypeManager only manages one specific thing. In order to support
ArrayCount, which is type related, but not a type, the TypeManager will
need to be able to store two types of things.
This CL changes the TypeManager to contain a UniqueAllocator and proxies
the needed Get, Find and iteration methods to that allocator. This will
allow another allocator to be added for ArrayCount later.
Bug: tint:1718
Change-Id: I0f952eb5c3ef90a7c85dead14d11b657dceba951
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112640
Commit-Queue: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/sem/type_manager.h b/src/tint/sem/type_manager.h
index 636b7a0..72f843a 100644
--- a/src/tint/sem/type_manager.h
+++ b/src/tint/sem/type_manager.h
@@ -25,10 +25,10 @@
namespace tint::sem {
/// The type manager holds all the pointers to the known types.
-class TypeManager final : public utils::UniqueAllocator<Type> {
+class TypeManager final {
public:
/// Iterator is the type returned by begin() and end()
- using Iterator = utils::BlockAllocator<Type>::ConstIterator;
+ using TypeIterator = utils::BlockAllocator<Type>::ConstIterator;
/// Constructor
TypeManager();
@@ -55,30 +55,38 @@
/// @return the Manager that wraps `inner`
static TypeManager Wrap(const TypeManager& inner) {
TypeManager out;
- out.items = inner.items;
+ out.types_.Wrap(inner.types_);
return out;
}
- /// @param args the arguments used to create the temporary type used for the search.
- /// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the type
+ /// @param args the arguments used to construct the object.
+ /// @return a pointer to an instance of `T` with the provided arguments.
+ /// If an existing instance of `T` has been constructed, then the same
+ /// pointer is returned.
+ template <typename TYPE,
+ typename _ = std::enable_if<traits::IsTypeOrDerived<TYPE, sem::Type>>,
+ typename... ARGS>
+ TYPE* Get(ARGS&&... args) {
+ return types_.Get<TYPE>(std::forward<ARGS>(args)...);
+ }
+
+ /// @param args the arguments used to create the temporary used for the search.
+ /// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the item
/// was not found.
- template <typename TYPE, typename... ARGS>
+ template <typename TYPE,
+ typename _ = std::enable_if<traits::IsTypeOrDerived<TYPE, sem::Type>>,
+ typename... ARGS>
TYPE* Find(ARGS&&... args) const {
- // Create a temporary T instance on the stack so that we can hash it, and
- // use it for equality lookup for the std::unordered_set.
- TYPE key{args...};
- auto hash = Hasher{}(key);
- auto it = items.find(Entry{hash, &key});
- if (it != items.end()) {
- return static_cast<TYPE*>(it->ptr);
- }
- return nullptr;
+ return types_.Find<TYPE>(std::forward<ARGS>(args)...);
}
/// @returns an iterator to the beginning of the types
- Iterator begin() const { return allocator.Objects().begin(); }
+ TypeIterator begin() const { return types_.begin(); }
/// @returns an iterator to the end of the types
- Iterator end() const { return allocator.Objects().end(); }
+ TypeIterator end() const { return types_.end(); }
+
+ private:
+ utils::UniqueAllocator<Type> types_;
};
} // namespace tint::sem
diff --git a/src/tint/utils/unique_allocator.h b/src/tint/utils/unique_allocator.h
index 1297701..25681cd 100644
--- a/src/tint/utils/unique_allocator.h
+++ b/src/tint/utils/unique_allocator.h
@@ -28,6 +28,9 @@
template <typename T, typename HASH = std::hash<T>, typename EQUAL = std::equal_to<T>>
class UniqueAllocator {
public:
+ /// Iterator is the type returned by begin() and end()
+ using Iterator = typename BlockAllocator<T>::ConstIterator;
+
/// @param args the arguments used to construct the object.
/// @return a pointer to an instance of `T` with the provided arguments.
/// If an existing instance of `T` has been constructed, then the same
@@ -49,7 +52,36 @@
return ptr;
}
- protected:
+ /// @param args the arguments used to create the temporary used for the search.
+ /// @return a pointer to an instance of `T` with the provided arguments, or nullptr if the item
+ /// was not found.
+ template <typename TYPE = T, typename... ARGS>
+ TYPE* Find(ARGS&&... args) const {
+ // Create a temporary T instance on the stack so that we can hash it, and
+ // use it for equality lookup for the std::unordered_set.
+ TYPE key{args...};
+ auto hash = Hasher{}(key);
+ auto it = items.find(Entry{hash, &key});
+ if (it != items.end()) {
+ return static_cast<TYPE*>(it->ptr);
+ }
+ return nullptr;
+ }
+
+ /// Wrap sets this allocator to the objects created with the content of `inner`.
+ /// The allocator after Wrap is intended to temporarily extend the objects
+ /// of an existing immutable UniqueAllocator.
+ /// As the copied objects are owned by `inner`, `inner` must not be destructed
+ /// or assigned while using this allocator.
+ /// @param o the immutable UniqueAlllocator to extend
+ void Wrap(const UniqueAllocator<T, HASH, EQUAL>& o) { items = o.items; }
+
+ /// @returns an iterator to the beginning of the types
+ Iterator begin() const { return allocator.Objects().begin(); }
+ /// @returns an iterator to the end of the types
+ Iterator end() const { return allocator.Objects().end(); }
+
+ private:
/// The hash function
using Hasher = HASH;
/// The equality function