Преглед изворни кода

Converting core/. log_snapshot_ring uses DataMutex

Kenny Mecham пре 2 недеља
родитељ
комит
996819ce40

+ 9 - 10
Sunrise/src/core/logging/log.cpp

@@ -7,8 +7,11 @@
 #include <atomic>
 #include <cstdio>
 #include <cstring>
+#include <mutex>
+#include <shared_mutex>
 
 #include "../filesystem/path.h"
+#include "core/threading/srw_lock.h"
 #include "snapshot/internal.h"
 
 namespace sunrise::core::log {
@@ -42,7 +45,7 @@ constexpr std::size_t kEventTextCapacity =
 constexpr std::size_t kStampCapacity = 32;
 
 struct LogState {
-    SRWLOCK lock{SRWLOCK_INIT};
+    threading::SrwLock lock{};
     std::array<std::atomic<Level>, static_cast<std::size_t>(Channel::count)> levels{};
     HANDLE file{INVALID_HANDLE_VALUE};
     /** Tick the sinks opened on. Every line carries its offset from this, so stalls are visible. */
@@ -135,7 +138,7 @@ Settings defaults() noexcept {
 
 /** Applies log thresholds and opens the optional file sink. */
 bool initialize(void* module, const Settings& settings) noexcept {
-    AcquireSRWLockExclusive(&g_log.lock);
+    const std::lock_guard lock(g_log.lock);
     // Resetting under the lifetime lock prevents an admitted writer from repopulating stale view.
     snapshot::internal::reset();
     if (g_log.file != INVALID_HANDLE_VALUE) {
@@ -159,13 +162,13 @@ bool initialize(void* module, const Settings& settings) noexcept {
             level.store(Level::off, std::memory_order_relaxed);
         }
     }
-    ReleaseSRWLockExclusive(&g_log.lock);
     return ready;
 }
 
 /** Closes the optional sink and clears the bounded in-memory view. */
 void shutdown() noexcept {
-    AcquireSRWLockExclusive(&g_log.lock);
+    const std::lock_guard lock(g_log.lock);
+
     g_log.initialized = false;
     for (std::atomic<Level>& level : g_log.levels) {
         level.store(Level::off, std::memory_order_relaxed);
@@ -177,7 +180,6 @@ void shutdown() noexcept {
     }
     // The same lifetime lock excludes writers until both sinks and retained entries are empty.
     snapshot::internal::reset();
-    ReleaseSRWLockExclusive(&g_log.lock);
 }
 
 /** Writes one line straight to the debugger, bypassing the sinks and every threshold. */
@@ -194,9 +196,8 @@ void early(std::string_view event) noexcept {
 
 /** Reports whether an event would be emitted, so callers can skip the cost of building one. */
 bool accepts(Channel channel, Level level) noexcept {
-    AcquireSRWLockShared(&g_log.lock);
+    const std::shared_lock lock(g_log.lock);
     const bool admitted = g_log.initialized && enabled(channel, level);
-    ReleaseSRWLockShared(&g_log.lock);
     return admitted;
 }
 
@@ -208,9 +209,8 @@ void write(Channel channel, Level level, std::string_view event) noexcept {
         return;
     }
 
-    AcquireSRWLockShared(&g_log.lock);
+    const std::shared_lock lock(g_log.lock);
     if (!g_log.initialized || !enabled(channel, level)) {
-        ReleaseSRWLockShared(&g_log.lock);
         return;
     }
 
@@ -248,7 +248,6 @@ void write(Channel channel, Level level, std::string_view event) noexcept {
     g_writers.fetch_sub(1, std::memory_order_acq_rel);
     // Record after sink writes while the shared lifetime lock still excludes shutdown reset.
     snapshot::internal::record(channel, level, std::string_view(line.data(), snapshotLength));
-    ReleaseSRWLockShared(&g_log.lock);
 }
 
 /** Formats and emits one debug event carrying a duration in the ms field. */

+ 34 - 34
Sunrise/src/core/logging/snapshot/log_snapshot_ring.cpp

@@ -4,6 +4,7 @@
 #include <array>
 #include <limits>
 
+#include "core/threading/data_mutex.h"
 #include "internal.h"
 
 namespace sunrise::core::log::snapshot {
@@ -13,14 +14,13 @@ namespace {
 constexpr std::size_t kTextTerminatorBytes = 1;
 
 struct RingState {
-    SRWLOCK lock{SRWLOCK_INIT};
     std::array<Entry, kEntryCapacity> entries{};
     std::size_t nextIndex{};
     std::size_t count{};
     std::uint64_t overwrittenCount{};
 };
 
-RingState g_ring;
+threading::SharedDataMutex<RingState> g_ring;
 
 /** @param channel Value to inspect. @return True for a defined log channel. */
 [[nodiscard]] bool valid_channel(Channel channel) noexcept {
@@ -62,15 +62,15 @@ std::uint64_t Snapshot::overwritten_count() const noexcept {
 /** @return A value-owned chronological copy of all retained events. */
 Snapshot take() noexcept {
     Snapshot result;
-    AcquireSRWLockShared(&g_ring.lock);
-    result.count_ = g_ring.count;
-    result.overwrittenCount_ = g_ring.overwrittenCount;
-    const std::size_t firstIndex =
-        (g_ring.nextIndex + kEntryCapacity - g_ring.count) % kEntryCapacity;
-    for (std::size_t index = 0; index < g_ring.count; ++index) {
-        result.entries_[index] = g_ring.entries[(firstIndex + index) % kEntryCapacity];
-    }
-    ReleaseSRWLockShared(&g_ring.lock);
+    g_ring.lock_read([&result](const RingState& ring) {
+        result.count_ = ring.count;
+        result.overwrittenCount_ = ring.overwrittenCount;
+        const std::size_t firstIndex =
+            (ring.nextIndex + kEntryCapacity - ring.count) % kEntryCapacity;
+        for (std::size_t index = 0; index < ring.count; ++index) {
+            result.entries_[index] = ring.entries[(firstIndex + index) % kEntryCapacity];
+        }
+    });
     return result;
 }
 
@@ -78,12 +78,12 @@ namespace internal {
 
 /** Clears retained events before a new logger lifecycle starts. */
 void reset() noexcept {
-    AcquireSRWLockExclusive(&g_ring.lock);
-    g_ring.entries = {};
-    g_ring.nextIndex = 0;
-    g_ring.count = 0;
-    g_ring.overwrittenCount = 0;
-    ReleaseSRWLockExclusive(&g_ring.lock);
+    g_ring.lock_write([](RingState& ring) {
+        ring.entries = {};
+        ring.nextIndex = 0;
+        ring.count = 0;
+        ring.overwrittenCount = 0;
+    });
 }
 
 /**
@@ -97,23 +97,23 @@ void record(Channel channel, Level level, std::string_view text) noexcept {
         return;
     }
 
-    AcquireSRWLockExclusive(&g_ring.lock);
-    Entry& entry = g_ring.entries[g_ring.nextIndex];
-    entry = {};
-    entry.channel_ = channel;
-    entry.level_ = level;
-    const std::size_t maximumText = entry.text_.size() - kTextTerminatorBytes;
-    entry.textLength_ = (std::min)(text.size(), maximumText);
-    if (entry.textLength_ != 0) {
-        std::copy_n(text.data(), entry.textLength_, entry.text_.data());
-    }
-    g_ring.nextIndex = (g_ring.nextIndex + 1) % kEntryCapacity;
-    if (g_ring.count < kEntryCapacity) {
-        ++g_ring.count;
-    } else if (g_ring.overwrittenCount != (std::numeric_limits<std::uint64_t>::max)()) {
-        ++g_ring.overwrittenCount;
-    }
-    ReleaseSRWLockExclusive(&g_ring.lock);
+    g_ring.lock_write([channel, level, text](RingState& ring) {
+        Entry& entry = ring.entries[ring.nextIndex];
+        entry = {};
+        entry.channel_ = channel;
+        entry.level_ = level;
+        const std::size_t maximumText = entry.text_.size() - kTextTerminatorBytes;
+        entry.textLength_ = (std::min)(text.size(), maximumText);
+        if (entry.textLength_ != 0) {
+            std::copy_n(text.data(), entry.textLength_, entry.text_.data());
+        }
+        ring.nextIndex = (ring.nextIndex + 1) % kEntryCapacity;
+        if (ring.count < kEntryCapacity) {
+            ++ring.count;
+        } else if (ring.overwrittenCount != (std::numeric_limits<std::uint64_t>::max)()) {
+            ++ring.overwrittenCount;
+        }
+    });
 }
 
 } // namespace internal

+ 5 - 10
Sunrise/src/core/runtime/core_runtime.cpp

@@ -7,6 +7,7 @@
 #include <atomic>
 #include <cstdint>
 #include <cstdio>
+#include <mutex>
 #include <string_view>
 
 #include "../../client/runtime/host/game_host_classification.h"
@@ -26,12 +27,13 @@
 #include "../ui/modules/logs/logs.h"
 #include "../ui/modules/registry/ui_module_registry.h"
 #include "../ui/runtime/ui_visibility_runtime.h"
+#include "core/threading/srw_lock.h"
 
 namespace sunrise::core {
 namespace {
 
 std::atomic_bool g_initialized{false};
-SRWLOCK g_runtimeLock{SRWLOCK_INIT};
+threading::SrwLock g_runtimeLock{};
 
 /** The installed public package headers live beside the game executable. */
 constexpr std::wstring_view kInstalledPackagesDirectory = L"packages";
@@ -136,9 +138,8 @@ void report_stage_failure(const char* stage) noexcept {
 
 /** Initializes every runtime layer in dependency order. */
 bool initialize(void* module) noexcept {
-    AcquireSRWLockExclusive(&g_runtimeLock);
+    const std::lock_guard lock(g_runtimeLock);
     if (g_initialized.load(std::memory_order_relaxed)) {
-        ReleaseSRWLockExclusive(&g_runtimeLock);
         return true;
     }
     // Taken before the first stage, so the reported duration covers settings and the sinks too.
@@ -146,7 +147,6 @@ bool initialize(void* module) noexcept {
 
     if (!settings::initialize(module)) {
         // Settings name their own failure; the sinks do not exist yet to carry a second line.
-        ReleaseSRWLockExclusive(&g_runtimeLock);
         return false;
     }
     state::unlocks::publish(settings::get().initialUnlocks);
@@ -200,26 +200,22 @@ bool initialize(void* module) noexcept {
         state::unlocks::clear();
         log::shutdown();
         settings::shutdown();
-        ReleaseSRWLockExclusive(&g_runtimeLock);
         return false;
     }
     g_initialized.store(true, std::memory_order_release);
     log::write(log::Channel::core, log::Level::info, "ev=initialize result=ok");
     log::write_elapsed(log::Channel::core, "ev=initialize phase=complete", startedTick, "ok");
-    ReleaseSRWLockExclusive(&g_runtimeLock);
     return true;
 }
 
 /** Stops every runtime layer in reverse dependency order. */
 bool shutdown() noexcept {
-    AcquireSRWLockExclusive(&g_runtimeLock);
+    const std::lock_guard lock(g_runtimeLock);
     if (!g_initialized.load(std::memory_order_acquire)) {
-        ReleaseSRWLockExclusive(&g_runtimeLock);
         return true;
     }
     if (!client::shutdown()) {
         // Server and State must remain valid while any Client hook is attached.
-        ReleaseSRWLockExclusive(&g_runtimeLock);
         return false;
     }
     g_initialized.store(false, std::memory_order_release);
@@ -237,7 +233,6 @@ bool shutdown() noexcept {
     state::unlocks::clear();
     log::shutdown();
     settings::shutdown();
-    ReleaseSRWLockExclusive(&g_runtimeLock);
     return true;
 }