From 5dd738d65a40ca9a290f4d6b2fea4eeaca03d017 Mon Sep 17 00:00:00 2001 From: Levi Behunin Date: Wed, 20 Oct 2021 05:03:41 -0600 Subject: [PATCH] Get logging to play nice with MPMCQueue Moved the backend thread function out of Impl constructor. Pass message as rvalue. memcpy message.data into temp message, then use that message as entry message. --- src/common/logging/backend.cpp | 68 +++++++++++++++++++++------------- src/common/logging/backend.h | 2 + src/common/logging/log.h | 4 +- src/common/logging/log_entry.h | 2 +- src/yuzu/main.cpp | 2 + 5 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 0ddcd93798..7ee230ea77 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -186,6 +186,10 @@ public: initialization_in_progress_suppress_logging = false; } + static void Start() { + instance->StartBackendThread(); + } + Impl(const Impl&) = delete; Impl& operator=(const Impl&) = delete; @@ -201,7 +205,7 @@ public: } void PushEntry(Class log_class, Level log_level, const char* filename, unsigned int line_num, - const char* function, std::string message) { + const char* function, fmt::string_view&& message) { if (!filter.CheckMessage(log_class, log_level)) return; const Entry& entry = @@ -211,33 +215,37 @@ public: private: Impl(const std::filesystem::path& file_backend_filename, const Filter& filter_) - : filter{filter_}, file_backend{file_backend_filename}, backend_thread{std::thread([this] { - Common::SetCurrentThreadName("yuzu:Log"); - Entry entry; - const auto write_logs = [this, &entry]() { - ForEachBackend([&entry](Backend& backend) { backend.Write(entry); }); - }; - while (true) { - if (!message_queue.try_pop(entry)) { - continue; - } - if (entry.final_entry) { - break; - } - write_logs(); - } - // Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a - // case where a system is repeatedly spamming logs even on close. - int max_logs_to_write = filter.IsDebug() ? INT_MAX : 100; - while (max_logs_to_write-- && message_queue.try_pop(entry)) { - write_logs(); - } - })} {} + : filter{filter_}, file_backend{file_backend_filename} {} ~Impl() { StopBackendThread(); } + void StartBackendThread() { + backend_thread = std::thread([this] { + Common::SetCurrentThreadName("yuzu:Log"); + Entry entry; + const auto write_logs = [this, &entry]() { + ForEachBackend([&entry](Backend& backend) { backend.Write(entry); }); + }; + while (true) { + if (!message_queue.try_pop(entry)) { + continue; + } + if (entry.final_entry) { + break; + } + write_logs(); + } + // Drain the logging queue. Only writes out up to MAX_LOGS_TO_WRITE to prevent a + // case where a system is repeatedly spamming logs even on close. + int max_logs_to_write = filter.IsDebug() ? INT_MAX : 100; + while (max_logs_to_write-- && message_queue.try_pop(entry)) { + write_logs(); + } + }); + } + void StopBackendThread() { Entry stop_entry{}; stop_entry.final_entry = true; @@ -246,11 +254,15 @@ private: } Entry CreateEntry(Class log_class, Level log_level, const char* filename, unsigned int line_nr, - const char* function, std::string message) const { + const char* function, fmt::string_view&& message) const { using std::chrono::duration_cast; using std::chrono::microseconds; using std::chrono::steady_clock; + auto len = message.size() + 1; + char* msg = new char[len]; + memcpy(msg, message.data(), len); + return { .timestamp = duration_cast(steady_clock::now() - time_origin), .log_class = log_class, @@ -258,7 +270,7 @@ private: .filename = filename, .line_num = line_nr, .function = function, - .message = message.c_str(), + .message = msg, .final_entry = false, }; } @@ -290,6 +302,10 @@ void Initialize() { Impl::Initialize(); } +void Start() { + Impl::Start(); +} + void DisableLoggingInTests() { initialization_in_progress_suppress_logging = true; } @@ -303,7 +319,7 @@ void SetColorConsoleBackendEnabled(bool enabled) { } void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, - unsigned int line_num, const char* function, const char* format, + unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args) { if (!initialization_in_progress_suppress_logging) { Impl::Instance().PushEntry(log_class, log_level, filename, line_num, function, diff --git a/src/common/logging/backend.h b/src/common/logging/backend.h index cb7839ee93..bf785f402e 100644 --- a/src/common/logging/backend.h +++ b/src/common/logging/backend.h @@ -14,6 +14,8 @@ class Filter; /// Initializes the logging system. This should be the first thing called in main. void Initialize(); +void Start(); + void DisableLoggingInTests(); /** diff --git a/src/common/logging/log.h b/src/common/logging/log.h index c186d55ef6..38d88fab47 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -24,12 +24,12 @@ constexpr const char* TrimSourcePath(std::string_view source) { /// Logs a message to the global logger, using fmt void FmtLogMessageImpl(Class log_class, Level log_level, const char* filename, - unsigned int line_num, const char* function, const char* format, + unsigned int line_num, const char* function, fmt::string_view format, const fmt::format_args& args); template void FmtLogMessage(Class log_class, Level log_level, const char* filename, unsigned int line_num, - const char* function, const char* format, const Args&... args) { + const char* function, fmt::string_view format, const Args&... args) { FmtLogMessageImpl(log_class, log_level, filename, line_num, function, format, fmt::make_format_args(args...)); } diff --git a/src/common/logging/log_entry.h b/src/common/logging/log_entry.h index a05d1441af..e61a481653 100644 --- a/src/common/logging/log_entry.h +++ b/src/common/logging/log_entry.h @@ -14,7 +14,7 @@ namespace Common::Log { * A log entry. Log entries are store in a structured format to permit more varied output * formatting on different frontends, as well as facilitating filtering and aggregation. */ -struct Entry { +struct Entry final { std::chrono::microseconds timestamp; Class log_class{}; Level log_level{}; diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 2af582fe5d..b33c70fbc8 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -287,6 +287,8 @@ GMainWindow::GMainWindow() ui->action_Fullscreen->setChecked(false); + Common::Log::Start(); + QStringList args = QApplication::arguments(); if (args.size() < 2) {