fixed_size_value_store.h 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. // Part of the Carbon Language project, under the Apache License v2.0 with LLVM
  2. // Exceptions. See /LICENSE for license information.
  3. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  4. #ifndef CARBON_TOOLCHAIN_BASE_FIXED_SIZE_VALUE_STORE_H_
  5. #define CARBON_TOOLCHAIN_BASE_FIXED_SIZE_VALUE_STORE_H_
  6. #include <concepts>
  7. #include <type_traits>
  8. #include "common/check.h"
  9. #include "llvm/ADT/SmallVector.h"
  10. #include "llvm/ADT/StringRef.h"
  11. #include "llvm/ADT/iterator_range.h"
  12. #include "toolchain/base/mem_usage.h"
  13. #include "toolchain/base/value_store_types.h"
  14. namespace Carbon {
  15. // A value store with a predetermined size.
  16. template <typename IdT, typename ValueT>
  17. class FixedSizeValueStore {
  18. public:
  19. using IdType = IdT;
  20. using ValueType = ValueStoreTypes<ValueT>::ValueType;
  21. using RefType = ValueStoreTypes<ValueT>::RefType;
  22. using ConstRefType = ValueStoreTypes<ValueT>::ConstRefType;
  23. // Makes a ValueStore of the specified size, but without initializing values.
  24. // Entries must be set before reading.
  25. static auto MakeForOverwriteWithExplicitSize(size_t size)
  26. -> FixedSizeValueStore {
  27. FixedSizeValueStore store;
  28. store.values_.resize_for_overwrite(size);
  29. return store;
  30. }
  31. // Makes a ValueStore of the same size as a source `ValueStoreT`, but without
  32. // initializing values. Entries must be set before reading.
  33. template <typename ValueStoreT>
  34. requires std::same_as<IdT, typename ValueStoreT::IdType>
  35. static auto MakeForOverwrite(const ValueStoreT& size_source)
  36. -> FixedSizeValueStore {
  37. FixedSizeValueStore store;
  38. store.values_.resize_for_overwrite(size_source.size());
  39. return store;
  40. }
  41. // Makes a ValueStore of the specified size, initialized to a default.
  42. static auto MakeWithExplicitSize(size_t size, ConstRefType default_value)
  43. -> FixedSizeValueStore {
  44. FixedSizeValueStore store;
  45. store.values_.resize(size, default_value);
  46. return store;
  47. }
  48. // Makes a ValueStore of the specified size, initialized to values returned
  49. // from a callback. This allows initializing non-copyable values.
  50. static auto MakeWithExplicitSizeFrom(
  51. size_t size, llvm::function_ref<auto()->ValueT> callable)
  52. -> FixedSizeValueStore {
  53. FixedSizeValueStore store;
  54. store.values_.reserve(size);
  55. for (auto _ : llvm::seq(size)) {
  56. store.values_.push_back(callable());
  57. }
  58. return store;
  59. }
  60. // Makes a ValueStore of the same size as a source `ValueStoreT`. This is
  61. // the safest constructor to use, since it ensures everything's initialized to
  62. // a default, and verifies a matching `IdT` for the size.
  63. template <typename ValueStoreT>
  64. requires std::same_as<IdT, typename ValueStoreT::IdType>
  65. explicit FixedSizeValueStore(const ValueStoreT& size_source,
  66. ConstRefType default_value) {
  67. values_.resize(size_source.size(), default_value);
  68. }
  69. // Makes a ValueStore using a mapped range of `source`. The `factory_fn`
  70. // receives each enumerated entry for construction of `ValueType`.
  71. template <typename ValueStoreT>
  72. requires std::same_as<IdT, typename ValueStoreT::IdType>
  73. explicit FixedSizeValueStore(
  74. const ValueStoreT& source,
  75. llvm::function_ref<
  76. auto(IdT, typename ValueStoreT::ConstRefType)->ValueType>
  77. factory_fn)
  78. : values_(llvm::map_range(source.enumerate(), factory_fn)) {}
  79. // Move-only.
  80. FixedSizeValueStore(FixedSizeValueStore&&) noexcept = default;
  81. auto operator=(FixedSizeValueStore&&) noexcept
  82. -> FixedSizeValueStore& = default;
  83. // Sets the value for an ID.
  84. auto Set(IdT id, ValueType value) -> void {
  85. CARBON_DCHECK(id.index >= 0, "{0}", id);
  86. values_[id.index] = value;
  87. }
  88. // Returns a mutable value for an ID.
  89. auto Get(IdT id) -> RefType {
  90. CARBON_DCHECK(id.index >= 0, "{0}", id);
  91. return values_[id.index];
  92. }
  93. // Returns the value for an ID.
  94. auto Get(IdT id) const -> ConstRefType {
  95. CARBON_DCHECK(id.index >= 0, "{0}", id);
  96. return values_[id.index];
  97. }
  98. // Collects memory usage of the values.
  99. auto CollectMemUsage(MemUsage& mem_usage, llvm::StringRef label) const
  100. -> void {
  101. mem_usage.Collect(label.str(), values_);
  102. }
  103. auto size() const -> size_t { return values_.size(); }
  104. auto values()
  105. -> llvm::iterator_range<typename llvm::SmallVector<ValueT, 0>::iterator> {
  106. return llvm::make_range(values_.begin(), values_.end());
  107. }
  108. auto values() const -> llvm::iterator_range<
  109. typename llvm::SmallVector<ValueT, 0>::const_iterator> {
  110. return llvm::make_range(values_.begin(), values_.end());
  111. }
  112. private:
  113. // Allow default construction for `Make` functions.
  114. FixedSizeValueStore() = default;
  115. // Storage for the `ValueT` objects, indexed by the id.
  116. llvm::SmallVector<ValueT, 0> values_;
  117. };
  118. } // namespace Carbon
  119. #endif // CARBON_TOOLCHAIN_BASE_FIXED_SIZE_VALUE_STORE_H_