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.
This commit is contained in:
Levi Behunin
2021-10-20 05:03:41 -06:00
parent a1261ab006
commit 5dd738d65a
5 changed files with 49 additions and 29 deletions

View File

@@ -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<microseconds>(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,

View File

@@ -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();
/**

View File

@@ -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 <typename... Args>
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...));
}

View File

@@ -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{};

View File

@@ -287,6 +287,8 @@ GMainWindow::GMainWindow()
ui->action_Fullscreen->setChecked(false);
Common::Log::Start();
QStringList args = QApplication::arguments();
if (args.size() < 2) {