diff options
author | Star Rauchenberger <fefferburbia@gmail.com> | 2024-12-20 14:33:43 -0500 |
---|---|---|
committer | Star Rauchenberger <fefferburbia@gmail.com> | 2024-12-20 14:33:43 -0500 |
commit | 3c49081df34fb1801063c0b538d12d4422fcf3f0 (patch) | |
tree | f4d267d953c97b0ee3e78730d8e36484abf7f096 | |
parent | 5a7559e39d2cd8306a99adbc6d39e90716b14687 (diff) | |
download | lingo-ap-tracker-3c49081df34fb1801063c0b538d12d4422fcf3f0.tar.gz lingo-ap-tracker-3c49081df34fb1801063c0b538d12d4422fcf3f0.tar.bz2 lingo-ap-tracker-3c49081df34fb1801063c0b538d12d4422fcf3f0.zip |
Fixed remaining thread unsafe APState/IPCState reads
Still would like to add some kind of wrapper object that TrackerState could use to read APState without locking, since it'll only ever be called from the thread that would do the mutating, but this is fine for now.
-rw-r--r-- | src/ap_state.cpp | 8 | ||||
-rw-r--r-- | src/ap_state.h | 9 | ||||
-rw-r--r-- | src/ipc_state.cpp | 4 | ||||
-rw-r--r-- | src/ipc_state.h | 2 | ||||
-rw-r--r-- | src/subway_map.cpp | 61 | ||||
-rw-r--r-- | src/subway_map.h | 6 | ||||
-rw-r--r-- | src/tracker_state.cpp | 23 |
7 files changed, 65 insertions, 48 deletions
diff --git a/src/ap_state.cpp b/src/ap_state.cpp index 908c3a8..4ac0cce 100644 --- a/src/ap_state.cpp +++ b/src/ap_state.cpp | |||
@@ -675,7 +675,9 @@ bool AP_IsPaintingShuffle() { | |||
675 | return GetState().painting_shuffle; | 675 | return GetState().painting_shuffle; |
676 | } | 676 | } |
677 | 677 | ||
678 | const std::map<std::string, std::string>& AP_GetPaintingMapping() { | 678 | std::map<std::string, std::string> AP_GetPaintingMapping() { |
679 | std::lock_guard state_guard(GetState().state_mutex); | ||
680 | |||
679 | return GetState().painting_mapping; | 681 | return GetState().painting_mapping; |
680 | } | 682 | } |
681 | 683 | ||
@@ -685,7 +687,7 @@ bool AP_IsPaintingMappedTo(const std::string& painting_id) { | |||
685 | return GetState().painting_codomain.count(painting_id); | 687 | return GetState().painting_codomain.count(painting_id); |
686 | } | 688 | } |
687 | 689 | ||
688 | const std::set<std::string>& AP_GetCheckedPaintings() { | 690 | std::set<std::string> AP_GetCheckedPaintings() { |
689 | return GetState().GetCheckedPaintings(); | 691 | return GetState().GetCheckedPaintings(); |
690 | } | 692 | } |
691 | 693 | ||
@@ -778,7 +780,7 @@ bool AP_IsSunwarpShuffle() { | |||
778 | return GetState().sunwarp_shuffle; | 780 | return GetState().sunwarp_shuffle; |
779 | } | 781 | } |
780 | 782 | ||
781 | const std::map<int, SunwarpMapping>& AP_GetSunwarpMapping() { | 783 | std::map<int, SunwarpMapping> AP_GetSunwarpMapping() { |
782 | return GetState().sunwarp_mapping; | 784 | return GetState().sunwarp_mapping; |
783 | } | 785 | } |
784 | 786 | ||
diff --git a/src/ap_state.h b/src/ap_state.h index a23b13d..2da0b8e 100644 --- a/src/ap_state.h +++ b/src/ap_state.h | |||
@@ -68,13 +68,11 @@ bool AP_IsColorShuffle(); | |||
68 | 68 | ||
69 | bool AP_IsPaintingShuffle(); | 69 | bool AP_IsPaintingShuffle(); |
70 | 70 | ||
71 | // WARNING: Not thread-safe! | 71 | std::map<std::string, std::string> AP_GetPaintingMapping(); |
72 | const std::map<std::string, std::string>& AP_GetPaintingMapping(); | ||
73 | 72 | ||
74 | bool AP_IsPaintingMappedTo(const std::string& painting_id); | 73 | bool AP_IsPaintingMappedTo(const std::string& painting_id); |
75 | 74 | ||
76 | // WARNING: Not thread-safe! | 75 | std::set<std::string> AP_GetCheckedPaintings(); |
77 | const std::set<std::string>& AP_GetCheckedPaintings(); | ||
78 | 76 | ||
79 | bool AP_IsPaintingChecked(const std::string& painting_id); | 77 | bool AP_IsPaintingChecked(const std::string& painting_id); |
80 | 78 | ||
@@ -100,8 +98,7 @@ SunwarpAccess AP_GetSunwarpAccess(); | |||
100 | 98 | ||
101 | bool AP_IsSunwarpShuffle(); | 99 | bool AP_IsSunwarpShuffle(); |
102 | 100 | ||
103 | // WARNING: Not thread-safe! | 101 | std::map<int, SunwarpMapping> AP_GetSunwarpMapping(); |
104 | const std::map<int, SunwarpMapping>& AP_GetSunwarpMapping(); | ||
105 | 102 | ||
106 | bool AP_HasReachedGoal(); | 103 | bool AP_HasReachedGoal(); |
107 | 104 | ||
diff --git a/src/ipc_state.cpp b/src/ipc_state.cpp index cba576c..1f8d286 100644 --- a/src/ipc_state.cpp +++ b/src/ipc_state.cpp | |||
@@ -103,7 +103,7 @@ struct IPCState { | |||
103 | return player_position; | 103 | return player_position; |
104 | } | 104 | } |
105 | 105 | ||
106 | const std::set<std::string>& GetSolvedPanels() { | 106 | std::set<std::string> GetSolvedPanels() { |
107 | std::lock_guard state_guard(state_mutex); | 107 | std::lock_guard state_guard(state_mutex); |
108 | 108 | ||
109 | return solved_panels; | 109 | return solved_panels; |
@@ -383,6 +383,6 @@ std::optional<std::tuple<int, int>> IPC_GetPlayerPosition() { | |||
383 | return GetState().GetPlayerPosition(); | 383 | return GetState().GetPlayerPosition(); |
384 | } | 384 | } |
385 | 385 | ||
386 | const std::set<std::string>& IPC_GetSolvedPanels() { | 386 | std::set<std::string> IPC_GetSolvedPanels() { |
387 | return GetState().GetSolvedPanels(); | 387 | return GetState().GetSolvedPanels(); |
388 | } | 388 | } |
diff --git a/src/ipc_state.h b/src/ipc_state.h index 84f3d29..7c9d68d 100644 --- a/src/ipc_state.h +++ b/src/ipc_state.h | |||
@@ -20,6 +20,6 @@ bool IPC_IsConnected(); | |||
20 | 20 | ||
21 | std::optional<std::tuple<int, int>> IPC_GetPlayerPosition(); | 21 | std::optional<std::tuple<int, int>> IPC_GetPlayerPosition(); |
22 | 22 | ||
23 | const std::set<std::string>& IPC_GetSolvedPanels(); | 23 | std::set<std::string> IPC_GetSolvedPanels(); |
24 | 24 | ||
25 | #endif /* end of include guard: IPC_STATE_H_6B3B0958 */ | 25 | #endif /* end of include guard: IPC_STATE_H_6B3B0958 */ |
diff --git a/src/subway_map.cpp b/src/subway_map.cpp index f896693..4ebc56a 100644 --- a/src/subway_map.cpp +++ b/src/subway_map.cpp | |||
@@ -16,28 +16,6 @@ constexpr int OWL_ACTUAL_SIZE = 32; | |||
16 | 16 | ||
17 | enum class ItemDrawType { kNone, kBox, kOwl }; | 17 | enum class ItemDrawType { kNone, kBox, kOwl }; |
18 | 18 | ||
19 | namespace { | ||
20 | |||
21 | std::optional<int> GetRealSubwayDoor(const SubwayItem subway_item) { | ||
22 | if (AP_IsSunwarpShuffle() && subway_item.sunwarp && | ||
23 | subway_item.sunwarp->type != SubwaySunwarpType::kFinal) { | ||
24 | int sunwarp_index = subway_item.sunwarp->dots - 1; | ||
25 | if (subway_item.sunwarp->type == SubwaySunwarpType::kExit) { | ||
26 | sunwarp_index += 6; | ||
27 | } | ||
28 | |||
29 | for (const auto &[start_index, mapping] : AP_GetSunwarpMapping()) { | ||
30 | if (start_index == sunwarp_index || mapping.exit_index == sunwarp_index) { | ||
31 | return GD_GetSunwarpDoors().at(mapping.dots - 1); | ||
32 | } | ||
33 | } | ||
34 | } | ||
35 | |||
36 | return subway_item.door; | ||
37 | } | ||
38 | |||
39 | } // namespace | ||
40 | |||
41 | SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { | 19 | SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { |
42 | SetBackgroundStyle(wxBG_STYLE_PAINT); | 20 | SetBackgroundStyle(wxBG_STYLE_PAINT); |
43 | 21 | ||
@@ -140,7 +118,7 @@ void SubwayMap::OnConnect() { | |||
140 | SubwaySunwarp final_sunwarp{.dots = 6, .type = SubwaySunwarpType::kFinal}; | 118 | SubwaySunwarp final_sunwarp{.dots = 6, .type = SubwaySunwarpType::kFinal}; |
141 | int final_sunwarp_item = GD_GetSubwayItemForSunwarp(final_sunwarp); | 119 | int final_sunwarp_item = GD_GetSubwayItemForSunwarp(final_sunwarp); |
142 | 120 | ||
143 | for (const auto &[index, mapping] : AP_GetSunwarpMapping()) { | 121 | for (const auto &[index, mapping] : sunwarp_mapping_) { |
144 | std::string tag = fmt::format("sunwarp{}", mapping.dots); | 122 | std::string tag = fmt::format("sunwarp{}", mapping.dots); |
145 | 123 | ||
146 | SubwaySunwarp fromWarp; | 124 | SubwaySunwarp fromWarp; |
@@ -197,15 +175,22 @@ void SubwayMap::OnConnect() { | |||
197 | } | 175 | } |
198 | 176 | ||
199 | void SubwayMap::UpdateIndicators() { | 177 | void SubwayMap::UpdateIndicators() { |
178 | if (AP_IsSunwarpShuffle()) { | ||
179 | sunwarp_mapping_ = AP_GetSunwarpMapping(); | ||
180 | } | ||
181 | |||
200 | if (AP_IsPaintingShuffle()) { | 182 | if (AP_IsPaintingShuffle()) { |
201 | for (const std::string &painting_id : AP_GetCheckedPaintings()) { | 183 | std::map<std::string, std::string> painting_mapping = |
184 | AP_GetPaintingMapping(); | ||
185 | std::set<std::string> remote_checked_paintings = AP_GetCheckedPaintings(); | ||
186 | |||
187 | for (const std::string &painting_id : remote_checked_paintings) { | ||
202 | if (!checked_paintings_.count(painting_id)) { | 188 | if (!checked_paintings_.count(painting_id)) { |
203 | checked_paintings_.insert(painting_id); | 189 | checked_paintings_.insert(painting_id); |
204 | 190 | ||
205 | if (AP_GetPaintingMapping().count(painting_id)) { | 191 | if (painting_mapping.count(painting_id)) { |
206 | std::optional<int> from_id = GD_GetSubwayItemForPainting(painting_id); | 192 | std::optional<int> from_id = GD_GetSubwayItemForPainting(painting_id); |
207 | std::optional<int> to_id = GD_GetSubwayItemForPainting( | 193 | std::optional<int> to_id = GD_GetSubwayItemForPainting(painting_mapping.at(painting_id)); |
208 | AP_GetPaintingMapping().at(painting_id)); | ||
209 | 194 | ||
210 | if (from_id && to_id) { | 195 | if (from_id && to_id) { |
211 | networks_.AddLink(*from_id, *to_id, false); | 196 | networks_.AddLink(*from_id, *to_id, false); |
@@ -600,6 +585,8 @@ void SubwayMap::Redraw() { | |||
600 | 585 | ||
601 | wxGCDC gcdc(dc); | 586 | wxGCDC gcdc(dc); |
602 | 587 | ||
588 | std::map<std::string, std::string> painting_mapping = AP_GetPaintingMapping(); | ||
589 | |||
603 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { | 590 | for (const SubwayItem &subway_item : GD_GetSubwayItems()) { |
604 | ItemDrawType draw_type = ItemDrawType::kNone; | 591 | ItemDrawType draw_type = ItemDrawType::kNone; |
605 | const wxBrush *brush_color = wxGREY_BRUSH; | 592 | const wxBrush *brush_color = wxGREY_BRUSH; |
@@ -641,7 +628,7 @@ void SubwayMap::Redraw() { | |||
641 | if (checked_paintings_.count(painting_id)) { | 628 | if (checked_paintings_.count(painting_id)) { |
642 | has_checked_painting = true; | 629 | has_checked_painting = true; |
643 | 630 | ||
644 | if (AP_GetPaintingMapping().count(painting_id)) { | 631 | if (painting_mapping.count(painting_id)) { |
645 | has_mapped_painting = true; | 632 | has_mapped_painting = true; |
646 | } else if (AP_IsPaintingMappedTo(painting_id)) { | 633 | } else if (AP_IsPaintingMappedTo(painting_id)) { |
647 | has_codomain_painting = true; | 634 | has_codomain_painting = true; |
@@ -803,6 +790,24 @@ void SubwayMap::SetZoom(double zoom, wxPoint static_point) { | |||
803 | zoom_slider_->SetValue((zoom - 1.0) / 0.25); | 790 | zoom_slider_->SetValue((zoom - 1.0) / 0.25); |
804 | } | 791 | } |
805 | 792 | ||
793 | std::optional<int> SubwayMap::GetRealSubwayDoor(const SubwayItem subway_item) { | ||
794 | if (AP_IsSunwarpShuffle() && subway_item.sunwarp && | ||
795 | subway_item.sunwarp->type != SubwaySunwarpType::kFinal) { | ||
796 | int sunwarp_index = subway_item.sunwarp->dots - 1; | ||
797 | if (subway_item.sunwarp->type == SubwaySunwarpType::kExit) { | ||
798 | sunwarp_index += 6; | ||
799 | } | ||
800 | |||
801 | for (const auto &[start_index, mapping] : sunwarp_mapping_) { | ||
802 | if (start_index == sunwarp_index || mapping.exit_index == sunwarp_index) { | ||
803 | return GD_GetSunwarpDoors().at(mapping.dots - 1); | ||
804 | } | ||
805 | } | ||
806 | } | ||
807 | |||
808 | return subway_item.door; | ||
809 | } | ||
810 | |||
806 | quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int &id) const { | 811 | quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int &id) const { |
807 | const SubwayItem &subway_item = GD_GetSubwayItem(id); | 812 | const SubwayItem &subway_item = GD_GetSubwayItem(id); |
808 | return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y), | 813 | return {static_cast<float>(subway_item.x), static_cast<float>(subway_item.y), |
diff --git a/src/subway_map.h b/src/subway_map.h index feee8ff..6aa31f5 100644 --- a/src/subway_map.h +++ b/src/subway_map.h | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <quadtree/Quadtree.h> | 16 | #include <quadtree/Quadtree.h> |
17 | 17 | ||
18 | #include "ap_state.h" | ||
18 | #include "game_data.h" | 19 | #include "game_data.h" |
19 | #include "network_set.h" | 20 | #include "network_set.h" |
20 | 21 | ||
@@ -50,6 +51,8 @@ class SubwayMap : public wxPanel { | |||
50 | void SetScrollSpeed(int scroll_x, int scroll_y); | 51 | void SetScrollSpeed(int scroll_x, int scroll_y); |
51 | void SetZoom(double zoom, wxPoint static_point); | 52 | void SetZoom(double zoom, wxPoint static_point); |
52 | 53 | ||
54 | std::optional<int> GetRealSubwayDoor(const SubwayItem subway_item); | ||
55 | |||
53 | wxImage map_image_; | 56 | wxImage map_image_; |
54 | wxImage owl_image_; | 57 | wxImage owl_image_; |
55 | wxBitmap unchecked_eye_; | 58 | wxBitmap unchecked_eye_; |
@@ -87,6 +90,9 @@ class SubwayMap : public wxPanel { | |||
87 | 90 | ||
88 | NetworkSet networks_; | 91 | NetworkSet networks_; |
89 | std::set<std::string> checked_paintings_; | 92 | std::set<std::string> checked_paintings_; |
93 | |||
94 | // Cached from APState. | ||
95 | std::map<int, SunwarpMapping> sunwarp_mapping_; | ||
90 | }; | 96 | }; |
91 | 97 | ||
92 | #endif /* end of include guard: SUBWAY_MAP_H_BD2D843E */ | 98 | #endif /* end of include guard: SUBWAY_MAP_H_BD2D843E */ |
diff --git a/src/tracker_state.cpp b/src/tracker_state.cpp index 4a49fac..eee43e4 100644 --- a/src/tracker_state.cpp +++ b/src/tracker_state.cpp | |||
@@ -192,6 +192,10 @@ class StateCalculator { | |||
192 | : options_(options) {} | 192 | : options_(options) {} |
193 | 193 | ||
194 | void Calculate() { | 194 | void Calculate() { |
195 | painting_mapping_ = AP_GetPaintingMapping(); | ||
196 | checked_paintings_ = AP_GetCheckedPaintings(); | ||
197 | sunwarp_mapping_ = AP_GetSunwarpMapping(); | ||
198 | |||
195 | std::list<int> panel_boundary; | 199 | std::list<int> panel_boundary; |
196 | std::list<int> painting_boundary; | 200 | std::list<int> painting_boundary; |
197 | std::list<Exit> flood_boundary; | 201 | std::list<Exit> flood_boundary; |
@@ -231,12 +235,12 @@ class StateCalculator { | |||
231 | reachable_changed = true; | 235 | reachable_changed = true; |
232 | 236 | ||
233 | PaintingExit cur_painting = GD_GetPaintingExit(painting_id); | 237 | PaintingExit cur_painting = GD_GetPaintingExit(painting_id); |
234 | if (AP_GetPaintingMapping().count(cur_painting.internal_id) && | 238 | if (painting_mapping_.count(cur_painting.internal_id) && |
235 | AP_GetCheckedPaintings().count(cur_painting.internal_id)) { | 239 | checked_paintings_.count(cur_painting.internal_id)) { |
236 | Exit painting_exit; | 240 | Exit painting_exit; |
237 | PaintingExit target_painting = | 241 | PaintingExit target_painting = |
238 | GD_GetPaintingExit(GD_GetPaintingByName( | 242 | GD_GetPaintingExit(GD_GetPaintingByName( |
239 | AP_GetPaintingMapping().at(cur_painting.internal_id))); | 243 | painting_mapping_.at(cur_painting.internal_id))); |
240 | painting_exit.source_room = cur_painting.room; | 244 | painting_exit.source_room = cur_painting.room; |
241 | painting_exit.destination_room = target_painting.room; | 245 | painting_exit.destination_room = target_painting.room; |
242 | painting_exit.type = EntranceType::kPainting; | 246 | painting_exit.type = EntranceType::kPainting; |
@@ -295,8 +299,8 @@ class StateCalculator { | |||
295 | 299 | ||
296 | if (AP_IsSunwarpShuffle()) { | 300 | if (AP_IsSunwarpShuffle()) { |
297 | for (int index : room_obj.sunwarps) { | 301 | for (int index : room_obj.sunwarps) { |
298 | if (AP_GetSunwarpMapping().count(index)) { | 302 | if (sunwarp_mapping_.count(index)) { |
299 | const SunwarpMapping& sm = AP_GetSunwarpMapping().at(index); | 303 | const SunwarpMapping& sm = sunwarp_mapping_.at(index); |
300 | 304 | ||
301 | new_boundary.push_back( | 305 | new_boundary.push_back( |
302 | {.source_room = room_exit.destination_room, | 306 | {.source_room = room_exit.destination_room, |
@@ -317,8 +321,7 @@ class StateCalculator { | |||
317 | if (AP_IsPilgrimageEnabled()) { | 321 | if (AP_IsPilgrimageEnabled()) { |
318 | int pilgrimage_start_id = GD_GetRoomByName("Hub Room"); | 322 | int pilgrimage_start_id = GD_GetRoomByName("Hub Room"); |
319 | if (AP_IsSunwarpShuffle()) { | 323 | if (AP_IsSunwarpShuffle()) { |
320 | for (const auto& [start_index, mapping] : | 324 | for (const auto& [start_index, mapping] : sunwarp_mapping_) { |
321 | AP_GetSunwarpMapping()) { | ||
322 | if (mapping.dots == 1) { | 325 | if (mapping.dots == 1) { |
323 | pilgrimage_start_id = GD_GetRoomForSunwarp(start_index); | 326 | pilgrimage_start_id = GD_GetRoomForSunwarp(start_index); |
324 | } | 327 | } |
@@ -578,7 +581,7 @@ class StateCalculator { | |||
578 | if (AP_IsSunwarpShuffle()) { | 581 | if (AP_IsSunwarpShuffle()) { |
579 | pilgrimage_pairs = std::vector<std::tuple<int, int>>(5); | 582 | pilgrimage_pairs = std::vector<std::tuple<int, int>>(5); |
580 | 583 | ||
581 | for (const auto& [start_index, mapping] : AP_GetSunwarpMapping()) { | 584 | for (const auto& [start_index, mapping] : sunwarp_mapping_) { |
582 | if (mapping.dots > 1) { | 585 | if (mapping.dots > 1) { |
583 | std::get<1>(pilgrimage_pairs[mapping.dots - 2]) = start_index; | 586 | std::get<1>(pilgrimage_pairs[mapping.dots - 2]) = start_index; |
584 | } | 587 | } |
@@ -649,6 +652,10 @@ class StateCalculator { | |||
649 | bool pilgrimage_doable_ = false; | 652 | bool pilgrimage_doable_ = false; |
650 | 653 | ||
651 | std::map<int, std::list<int>> paths_; | 654 | std::map<int, std::list<int>> paths_; |
655 | |||
656 | std::map<std::string, std::string> painting_mapping_; | ||
657 | std::set<std::string> checked_paintings_; | ||
658 | std::map<int, SunwarpMapping> sunwarp_mapping_; | ||
652 | }; | 659 | }; |
653 | 660 | ||
654 | } // namespace | 661 | } // namespace |