Explorar el Código

Guard the new build-data catalogs with SrwLock

Master's #91 removed the build_data Lock type. The records, rewards, nodes and SObject catalogs still used it, so they follow the sibling catalogs onto core::threading::SrwLock with std::lock_guard and std::shared_lock.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017y4GeUXaw46fq2mDFGBVHN
stan hace 4 días
padre
commit
571fa8a36c

+ 12 - 9
Sunrise/src/state/build_data/nodes/node_catalog.cpp

@@ -1,14 +1,17 @@
 #include "node_catalog.h"
 
+#include <shared_mutex>
+
 #include "../../record_claims/objective_slot_table.h"
 #include "../../record_claims/record_claims.h"
 #include "../../unlocks/definition.h"
 #include "../table.h"
+#include "core/threading/srw_lock.h"
 
 namespace sunrise::state::build_data::nodes {
 namespace {
 
-Lock g_lock;
+core::threading::SrwLock g_lock;
 Table<Definition, kDefinitionCapacity> g_definitions;
 
 } // namespace
@@ -16,7 +19,7 @@ Table<Definition, kDefinitionCapacity> g_definitions;
 /** Clears every generated node definition under the catalog lock. */
 void clear() noexcept {
     {
-        const Lock::Exclusive guard(g_lock);
+        const std::lock_guard guard(g_lock);
         g_definitions.clear();
     }
     record_claims::invalidate_build_data_cache();
@@ -43,7 +46,7 @@ bool replace(std::span<const Definition> definitions) noexcept {
     }
     bool replaced = false;
     {
-        const Lock::Exclusive guard(g_lock);
+        const std::lock_guard guard(g_lock);
         replaced = g_definitions.replace(definitions);
     }
     if (replaced) {
@@ -54,19 +57,19 @@ bool replace(std::span<const Definition> definitions) noexcept {
 
 /** Copies every row in native node order. */
 bool snapshot(std::span<Definition> output, std::size_t& count) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     return g_definitions.snapshot(output, count);
 }
 
 /** @return Number of generated node definitions, read under the lock. */
 std::size_t count() noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     return g_definitions.count();
 }
 
 /** Calls back for every node, under the shared lock. */
 void for_each(void* context, void (*visit)(void*, const Definition&) noexcept) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     for (const Definition& node : g_definitions.rows()) {
         visit(context, node);
     }
@@ -74,7 +77,7 @@ void for_each(void* context, void (*visit)(void*, const Definition&) noexcept) n
 
 /** Sets the visibility gate of every lore book category. */
 std::size_t apply_visibility(std::span<std::uint8_t> accountFlags) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     std::size_t set = 0;
     for (const Definition& node : g_definitions.rows()) {
         if (node.definitionIndex < kLoreNodeFirst || node.definitionIndex > kLoreNodeLast
@@ -90,7 +93,7 @@ std::size_t apply_visibility(std::span<std::uint8_t> accountFlags) noexcept {
 
 /** Opens lore categories whose gates read an otherwise-empty value slot. */
 std::size_t apply_category_gates(std::span<std::int32_t> objectiveValues) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     std::size_t set = 0;
     for (const Definition& node : g_definitions.rows()) {
         if (node.definitionIndex < kLoreNodeFirst || node.definitionIndex > kLoreNodeLast) {
@@ -121,7 +124,7 @@ std::size_t apply_category_gates(std::span<std::int32_t> objectiveValues) noexce
 
 /** Sets the character scoped visibility gates of the lore book categories. */
 std::size_t apply_character_visibility(std::span<std::byte> characterFlags) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     std::size_t set = 0;
     for (const Definition& node : g_definitions.rows()) {
         if (node.definitionIndex < kLoreNodeFirst || node.definitionIndex > kLoreNodeLast

+ 9 - 6
Sunrise/src/state/build_data/records/record_catalog.cpp

@@ -1,12 +1,15 @@
 #include "record_catalog.h"
 
+#include <shared_mutex>
+
 #include "../../record_claims/record_claims.h"
 #include "../table.h"
+#include "core/threading/srw_lock.h"
 
 namespace sunrise::state::build_data::records {
 namespace {
 
-Lock g_lock;
+core::threading::SrwLock g_lock;
 Table<Definition, kDefinitionCapacity> g_definitions;
 
 } // namespace
@@ -14,7 +17,7 @@ Table<Definition, kDefinitionCapacity> g_definitions;
 /** Clears every generated record definition under the catalog lock. */
 void clear() noexcept {
     {
-        const Lock::Exclusive guard(g_lock);
+        const std::lock_guard guard(g_lock);
         g_definitions.clear();
     }
     record_claims::invalidate_build_data_cache();
@@ -40,7 +43,7 @@ bool replace(std::span<const Definition> definitions) noexcept {
     }
     bool replaced = false;
     {
-        const Lock::Exclusive guard(g_lock);
+        const std::lock_guard guard(g_lock);
         replaced = g_definitions.replace(definitions);
     }
     if (replaced) {
@@ -51,7 +54,7 @@ bool replace(std::span<const Definition> definitions) noexcept {
 
 /** Finds one record by the native row a claim names. */
 bool find(std::uint16_t definitionIndex, Definition& definition) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     const std::span<const Definition> rows = g_definitions.rows();
     if (definitionIndex >= rows.size()) {
         return false;
@@ -62,13 +65,13 @@ bool find(std::uint16_t definitionIndex, Definition& definition) noexcept {
 
 /** Copies every row in native record order. */
 bool snapshot(std::span<Definition> output, std::size_t& count) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     return g_definitions.snapshot(output, count);
 }
 
 /** @return Number of generated record definitions, read under the lock. */
 std::size_t count() noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     return g_definitions.count();
 }
 

+ 6 - 3
Sunrise/src/state/build_data/records/rewards/reward_catalog.cpp

@@ -1,11 +1,14 @@
 #include "reward_catalog.h"
 
+#include <shared_mutex>
+
 #include "../../table.h"
+#include "core/threading/srw_lock.h"
 
 namespace sunrise::state::build_data::records::rewards {
 namespace {
 
-Lock g_lock;
+core::threading::SrwLock g_lock;
 Table<RewardRow, kRewardCapacity> g_rows;
 
 } // namespace
@@ -20,13 +23,13 @@ bool replace(std::span<const RewardRow> rows) noexcept {
     if (!valid(rows)) {
         return false;
     }
-    const Lock::Exclusive guard(g_lock);
+    const std::lock_guard guard(g_lock);
     return g_rows.replace(rows);
 }
 
 /** Visits every reward row naming one record, holding the catalog lock for the whole walk. */
 void visit_for_record(std::uint32_t recordHash, RowVisitor visitor, void* context) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     for (const RewardRow& row : g_rows.rows()) {
         if (row.recordHash != recordHash) {
             continue;

+ 9 - 6
Sunrise/src/state/build_data/sobjects/sobject_catalog.cpp

@@ -1,18 +1,21 @@
 #include "sobject_catalog.h"
 
+#include <shared_mutex>
+
 #include "../table.h"
+#include "core/threading/srw_lock.h"
 
 namespace sunrise::state::build_data::sobjects {
 namespace {
 
-Lock g_lock;
+core::threading::SrwLock g_lock;
 Table<Definition, kDefinitionCapacity> g_definitions;
 
 } // namespace
 
 /** Clears the table while no reader can observe a partial replacement. */
 void clear() noexcept {
-    const Lock::Exclusive guard(g_lock);
+    const std::lock_guard guard(g_lock);
     g_definitions.clear();
 }
 
@@ -32,19 +35,19 @@ bool replace(std::span<const Definition> definitions) noexcept {
     if (!valid(definitions)) {
         return false;
     }
-    const Lock::Exclusive guard(g_lock);
+    const std::lock_guard guard(g_lock);
     return g_definitions.replace(definitions);
 }
 
 /** Copies every row in incident-target order. */
 bool snapshot(std::span<Definition> output, std::size_t& count) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     return g_definitions.snapshot(output, count);
 }
 
 /** Finds one row by the target index an incident carries. */
 bool find(std::uint16_t targetIndex, Definition& definition) noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     const std::span<const Definition> rows = g_definitions.rows();
     if (targetIndex >= rows.size()) {
         return false;
@@ -55,7 +58,7 @@ bool find(std::uint16_t targetIndex, Definition& definition) noexcept {
 
 /** @return Number of installed rows, read under the lock. */
 std::size_t count() noexcept {
-    const Lock::Shared guard(g_lock);
+    const std::shared_lock guard(g_lock);
     return g_definitions.count();
 }