Skip to content

Commit 9fffe1e

Browse files
authored
Merge pull request #462 from OpenVicProject/add/pointmap-signals
Add invalidation signals to pathfinding classes
2 parents 8cbf58b + 7bad7a0 commit 9fffe1e

File tree

5 files changed

+48
-6
lines changed

5 files changed

+48
-6
lines changed

src/openvic-simulation/pathfinding/AStarPathing.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ namespace OpenVic {
2525
};
2626

2727
/** A* Pathfinding implementation
28-
29-
Requires that any pointer invalidation in PointMap must call reset_search()
3028
*/
3129
struct AStarPathing : public PathingBase<AStarPathingNode> {
3230
using PathingBase::PathingBase;

src/openvic-simulation/pathfinding/FringePathing.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@ namespace OpenVic {
2020
};
2121

2222
/** Fringe Pathfinding implementation
23-
24-
Requires that any pointer invalidation in PointMap must call reset_search()
2523
*/
2624
struct FringePathing : public PathingBase<FringePathingNode> {
2725
using PathingBase::PathingBase;

src/openvic-simulation/pathfinding/PathingBase.hpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <fmt/core.h>
66

77
#include "openvic-simulation/pathfinding/PointMap.hpp"
8+
#include "openvic-simulation/types/Signal.hpp"
89
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
910
#include "openvic-simulation/utility/ErrorMacros.hpp"
1011

@@ -34,7 +35,7 @@ namespace OpenVic {
3435
};
3536

3637
template<typename ValueT, typename KeyT = PointMap::points_key_type>
37-
struct PathingBase {
38+
struct PathingBase : observer {
3839
using search_node_type = PathingNodeBase<ValueT, KeyT>;
3940
using search_key_type = search_node_type::search_key_type;
4041
using search_value_type = search_node_type::search_value_type;
@@ -69,13 +70,31 @@ namespace OpenVic {
6970
search_iterator begin_point, search_iterator end_point, uint64_t pass, bool allow_partial_path
7071
) = 0;
7172

73+
void _on_point_invalidated(search_key_type id) {
74+
search_const_iterator it = search.find(id);
75+
if (it != search.end()) {
76+
search.unordered_erase(it);
77+
}
78+
}
79+
80+
void _on_point_map_destroyed() {
81+
point_map = nullptr;
82+
}
83+
7284
public:
7385
PathingBase(PointMap const* map) : point_map(map) {
7486
reserve_space(point_map->get_point_count());
87+
point_map->point_invalidated.connect(&PathingBase::_on_point_invalidated, this);
88+
point_map->points_pointers_invalidated.connect(&PathingBase::reset_search, this);
89+
point_map->destroyed.connect(&PathingBase::_on_point_map_destroyed, this);
7590
}
7691

7792
PathingBase(PointMap const& map) : PathingBase(&map) {}
7893

94+
virtual ~PathingBase() {
95+
this->disconnect_all();
96+
}
97+
7998
PointMap const& get_point_map() const {
8099
return *point_map;
81100
}
@@ -145,6 +164,8 @@ namespace OpenVic {
145164
std::vector<ivec2_t> get_point_path( //
146165
PointMap::points_key_type from_id, PointMap::points_key_type to_id, bool allow_partial_path = false
147166
) {
167+
OV_ERR_FAIL_COND_V(point_map == nullptr, std::vector<ivec2_t>());
168+
148169
search_iterator from_it = get_iterator_by_id(from_id);
149170
OV_ERR_FAIL_COND_V(from_it == search.end(), std::vector<ivec2_t>());
150171

@@ -177,6 +198,8 @@ namespace OpenVic {
177198
std::vector<PointMap::points_key_type> get_id_path( //
178199
PointMap::points_key_type from_id, PointMap::points_key_type to_id, bool allow_partial_path = false
179200
) {
201+
OV_ERR_FAIL_COND_V(point_map == nullptr, std::vector<PointMap::points_key_type>());
202+
180203
search_iterator from_it = get_iterator_by_id(from_id);
181204
OV_ERR_FAIL_COND_V(from_it == search.end(), std::vector<PointMap::points_key_type>());
182205

src/openvic-simulation/pathfinding/PointMap.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818

1919
using namespace OpenVic;
2020

21+
PointMap::~PointMap() {
22+
destroyed();
23+
}
24+
2125
int64_t PointMap::get_available_points() const {
2226
if (points.contains(last_free_id)) {
2327
int64_t cur_new_id = last_free_id + 1;
@@ -44,7 +48,11 @@ bool PointMap::try_add_point(
4448
return false;
4549
}
4650

51+
size_t prev_capacity = get_point_capacity();
4752
points[id] = Point { .position = position, .weight_scale = weight_scale, .enabled = true };
53+
if (OV_unlikely(prev_capacity != get_point_capacity())) {
54+
points_pointers_invalidated();
55+
}
4856

4957
for (points_key_type const& adj_id : adjacent_points) {
5058
connect_points(id, adj_id);
@@ -66,7 +74,11 @@ void PointMap::add_point(
6674
points_iterator found_pt = points.find(id);
6775

6876
if (found_pt == points.end()) {
77+
size_t prev_capacity = get_point_capacity();
6978
points[id] = Point { .position = position, .weight_scale = weight_scale, .enabled = true };
79+
if (OV_unlikely(get_point_capacity() != prev_capacity)) {
80+
points_pointers_invalidated();
81+
}
7082
} else {
7183
found_pt.value().position = position;
7284
found_pt.value().weight_scale = weight_scale;
@@ -156,6 +168,7 @@ void PointMap::remove_point(points_key_type id) {
156168

157169
points.unordered_erase(it);
158170
last_free_id = id;
171+
point_invalidated(id);
159172
}
160173

161174
bool PointMap::has_point(points_key_type id) const {
@@ -295,20 +308,23 @@ size_t PointMap::get_point_capacity() const {
295308
void PointMap::reserve_space(size_t num_nodes) {
296309
OV_ERR_FAIL_COND_MSG(num_nodes <= 0, fmt::format("New capacity must be greater than 0, new was: {}.", num_nodes));
297310
OV_ERR_FAIL_COND_MSG(
298-
num_nodes < points.capacity(),
311+
num_nodes <= points.capacity(),
299312
fmt::format("New capacity must be greater than current capacity: {}, new was: {}.", points.capacity(), num_nodes)
300313
);
301314
points.reserve(num_nodes);
315+
points_pointers_invalidated();
302316
}
303317

304318
void PointMap::shrink_to_fit() {
305319
points.shrink_to_fit();
320+
points_pointers_invalidated();
306321
}
307322

308323
void PointMap::clear() {
309324
last_free_id = 0;
310325
segments.clear();
311326
points.clear();
327+
points_pointers_invalidated();
312328
}
313329

314330
PointMap::points_key_type PointMap::get_closest_point(ivec2_t const& point, bool include_disabled) const {

src/openvic-simulation/pathfinding/PointMap.hpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include <tsl/ordered_set.h>
1010

1111
#include "openvic-simulation/types/EnumBitfield.hpp"
12+
#include "openvic-simulation/types/Signal.hpp"
1213
#include "openvic-simulation/types/Vector.hpp"
1314
#include "openvic-simulation/types/fixed_point/FixedPoint.hpp"
1415
#include "openvic-simulation/utility/Utility.hpp"
@@ -132,6 +133,12 @@ namespace OpenVic {
132133
mutable points_key_type last_free_id = 0;
133134

134135
public:
136+
mutable signal_property<PointMap, points_key_type> point_invalidated;
137+
mutable signal_property<PointMap> points_pointers_invalidated;
138+
mutable signal_property<PointMap> destroyed;
139+
140+
~PointMap();
141+
135142
int64_t get_available_points() const;
136143

137144
bool try_add_point(

0 commit comments

Comments
 (0)