1#ifndef PER_STATE_ARRAY_H
2#define PER_STATE_ARRAY_H
4#include "downward/per_state_information.h"
7#include <unordered_map>
15 ConstArrayView(
const T* p,
int size)
20 ConstArrayView(
const ConstArrayView<T>& other) =
default;
22 ConstArrayView<T>& operator=(
const ConstArrayView<T>& other) =
default;
24 const T& operator[](
int index)
const
26 assert(index >= 0 && index < size_);
30 int size()
const {
return size_; }
39 ArrayView(T* p,
int size)
44 ArrayView(
const ArrayView<T>& other) =
default;
46 ArrayView<T>& operator=(
const ArrayView<T>& other) =
default;
48 operator ConstArrayView<T>()
const {
return ConstArrayView<T>(p, size_); }
50 T& operator[](
int index)
52 assert(index >= 0 && index < size_);
56 const T& operator[](
int index)
const
58 assert(index >= 0 && index < size_);
62 int size()
const {
return size_; }
76template <
class Element>
77class PerStateArray :
public subscriber::Subscriber<StateRegistry> {
78 const std::vector<Element> default_array;
79 using EntryArrayVectorMap = std::unordered_map<
81 segmented_vector::SegmentedArrayVector<Element>*>;
82 EntryArrayVectorMap entry_arrays_by_registry;
84 mutable const StateRegistry* cached_registry;
85 mutable segmented_vector::SegmentedArrayVector<Element>* cached_entries;
87 segmented_vector::SegmentedArrayVector<Element>*
88 get_entries(
const StateRegistry* registry)
90 if (cached_registry != registry) {
91 cached_registry = registry;
92 auto it = entry_arrays_by_registry.find(registry);
93 if (it == entry_arrays_by_registry.end()) {
95 new segmented_vector::SegmentedArrayVector<Element>(
96 default_array.size());
97 entry_arrays_by_registry[registry] = cached_entries;
98 registry->subscribe(
this);
100 cached_entries = it->second;
104 cached_registry == registry &&
105 cached_entries == entry_arrays_by_registry[registry]);
106 return cached_entries;
109 const segmented_vector::SegmentedArrayVector<Element>*
110 get_entries(
const StateRegistry* registry)
const
112 if (cached_registry != registry) {
113 const auto it = entry_arrays_by_registry.find(registry);
114 if (it == entry_arrays_by_registry.end()) {
117 cached_registry = registry;
118 cached_entries =
const_cast<
119 segmented_vector::SegmentedArrayVector<Element>*
>(
123 assert(cached_registry == registry);
124 return cached_entries;
128 explicit PerStateArray(
const std::vector<Element>& default_array)
129 : default_array(default_array)
130 , cached_registry(nullptr)
131 , cached_entries(nullptr)
135 PerStateArray(
const PerStateArray<Element>&) =
delete;
136 PerStateArray& operator=(
const PerStateArray<Element>&) =
delete;
138 virtual ~PerStateArray()
override
140 for (
auto it : entry_arrays_by_registry) {
145 ArrayView<Element> operator[](
const State& state)
147 const StateRegistry* registry = state.get_registry();
149 std::cerr <<
"Tried to access per-state array with an unregistered "
150 <<
"state." << std::endl;
151 utils::exit_with(utils::ExitCode::SEARCH_CRITICAL_ERROR);
153 segmented_vector::SegmentedArrayVector<Element>* entries =
154 get_entries(registry);
155 int state_id = state.get_id().value;
156 assert(state.get_id() != StateID::no_state);
157 size_t virtual_size = registry->size();
158 assert(utils::in_bounds(state_id, *registry));
159 if (entries->size() < virtual_size) {
160 entries->resize(virtual_size, default_array.data());
162 return ArrayView<Element>((*entries)[state_id], default_array.size());
165 ConstArrayView<Element> operator[](
const State& state)
const
167 const StateRegistry* registry = state.get_registry();
169 std::cerr <<
"Tried to access per-state array with an unregistered "
170 <<
"state." << std::endl;
171 utils::exit_with(utils::ExitCode::SEARCH_CRITICAL_ERROR);
173 const segmented_vector::SegmentedArrayVector<Element>* entries =
174 get_entries(registry);
176 ABORT(
"PerStateArray::operator[] const tried to access "
177 "non-existing entry.");
179 int state_id = state.get_id().value;
180 assert(state.get_id() != StateID::no_state);
181 assert(utils::in_bounds(state_id, *registry));
182 int num_entries = entries->size();
183 if (state_id >= num_entries) {
184 ABORT(
"PerStateArray::operator[] const tried to access "
185 "non-existing entry.");
187 return ConstArrayView<Element>(
188 (*entries)[state_id],
189 default_array.size());
193 notify_service_destroyed(
const StateRegistry* registry)
override
195 delete entry_arrays_by_registry[registry];
196 entry_arrays_by_registry.erase(registry);
197 if (registry == cached_registry) {
198 cached_registry =
nullptr;
199 cached_entries =
nullptr;