fixed_size_value_store.h 5.1 KB

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