about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorStar Rauchenberger <fefferburbia@gmail.com>2024-12-20 14:33:43 -0500
committerStar Rauchenberger <fefferburbia@gmail.com>2024-12-20 14:33:43 -0500
commit3c49081df34fb1801063c0b538d12d4422fcf3f0 (patch)
treef4d267d953c97b0ee3e78730d8e36484abf7f096
parent5a7559e39d2cd8306a99adbc6d39e90716b14687 (diff)
downloadlingo-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.cpp8
-rw-r--r--src/ap_state.h9
-rw-r--r--src/ipc_state.cpp4
-rw-r--r--src/ipc_state.h2
-rw-r--r--src/subway_map.cpp61
-rw-r--r--src/subway_map.h6
-rw-r--r--src/tracker_state.cpp23
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
678const std::map<std::string, std::string>& AP_GetPaintingMapping() { 678std::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
688const std::set<std::string>& AP_GetCheckedPaintings() { 690std::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
781const std::map<int, SunwarpMapping>& AP_GetSunwarpMapping() { 783std::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
69bool AP_IsPaintingShuffle(); 69bool AP_IsPaintingShuffle();
70 70
71// WARNING: Not thread-safe! 71std::map<std::string, std::string> AP_GetPaintingMapping();
72const std::map<std::string, std::string>& AP_GetPaintingMapping();
73 72
74bool AP_IsPaintingMappedTo(const std::string& painting_id); 73bool AP_IsPaintingMappedTo(const std::string& painting_id);
75 74
76// WARNING: Not thread-safe! 75std::set<std::string> AP_GetCheckedPaintings();
77const std::set<std::string>& AP_GetCheckedPaintings();
78 76
79bool AP_IsPaintingChecked(const std::string& painting_id); 77bool AP_IsPaintingChecked(const std::string& painting_id);
80 78
@@ -100,8 +98,7 @@ SunwarpAccess AP_GetSunwarpAccess();
100 98
101bool AP_IsSunwarpShuffle(); 99bool AP_IsSunwarpShuffle();
102 100
103// WARNING: Not thread-safe! 101std::map<int, SunwarpMapping> AP_GetSunwarpMapping();
104const std::map<int, SunwarpMapping>& AP_GetSunwarpMapping();
105 102
106bool AP_HasReachedGoal(); 103bool 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
386const std::set<std::string>& IPC_GetSolvedPanels() { 386std::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
21std::optional<std::tuple<int, int>> IPC_GetPlayerPosition(); 21std::optional<std::tuple<int, int>> IPC_GetPlayerPosition();
22 22
23const std::set<std::string>& IPC_GetSolvedPanels(); 23std::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
17enum class ItemDrawType { kNone, kBox, kOwl }; 17enum class ItemDrawType { kNone, kBox, kOwl };
18 18
19namespace {
20
21std::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
41SubwayMap::SubwayMap(wxWindow *parent) : wxPanel(parent, wxID_ANY) { 19SubwayMap::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
199void SubwayMap::UpdateIndicators() { 177void 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
793std::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
806quadtree::Box<float> SubwayMap::GetItemBox::operator()(const int &id) const { 811quadtree::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