|
|
|
@ -6,6 +6,7 @@ |
|
|
|
#include <chrono>
|
|
|
|
#include <climits>
|
|
|
|
#include <exception>
|
|
|
|
#include <stop_token>
|
|
|
|
#include <thread>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
@ -186,6 +187,10 @@ public: |
|
|
|
initialization_in_progress_suppress_logging = false; |
|
|
|
} |
|
|
|
|
|
|
|
static void Start() { |
|
|
|
instance->StartBackendThread(); |
|
|
|
} |
|
|
|
|
|
|
|
Impl(const Impl&) = delete; |
|
|
|
Impl& operator=(const Impl&) = delete; |
|
|
|
|
|
|
|
@ -201,7 +206,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, std::string&& message) { |
|
|
|
if (!filter.CheckMessage(log_class, log_level)) |
|
|
|
return; |
|
|
|
const Entry& entry = |
|
|
|
@ -211,40 +216,41 @@ 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) { |
|
|
|
entry = message_queue.PopWait(); |
|
|
|
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.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 (!stop.stop_requested()) { |
|
|
|
entry = message_queue.PopWait(stop.get_token()); |
|
|
|
if (entry.filename != nullptr) { |
|
|
|
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.Pop(entry)) { |
|
|
|
write_logs(); |
|
|
|
} |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
void StopBackendThread() { |
|
|
|
Entry stop_entry{}; |
|
|
|
stop_entry.final_entry = true; |
|
|
|
message_queue.Push(stop_entry); |
|
|
|
stop.request_stop(); |
|
|
|
backend_thread.join(); |
|
|
|
} |
|
|
|
|
|
|
|
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, std::string&& message) const { |
|
|
|
using std::chrono::duration_cast; |
|
|
|
using std::chrono::microseconds; |
|
|
|
using std::chrono::steady_clock; |
|
|
|
@ -257,7 +263,6 @@ private: |
|
|
|
.line_num = line_nr, |
|
|
|
.function = function, |
|
|
|
.message = std::move(message), |
|
|
|
.final_entry = false, |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
@ -278,8 +283,9 @@ private: |
|
|
|
ColorConsoleBackend color_console_backend{}; |
|
|
|
FileBackend file_backend; |
|
|
|
|
|
|
|
std::stop_source stop; |
|
|
|
std::thread backend_thread; |
|
|
|
MPSCQueue<Entry> message_queue{}; |
|
|
|
MPSCQueue<Entry, true> message_queue{}; |
|
|
|
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()}; |
|
|
|
}; |
|
|
|
} // namespace
|
|
|
|
@ -288,6 +294,10 @@ void Initialize() { |
|
|
|
Impl::Initialize(); |
|
|
|
} |
|
|
|
|
|
|
|
void Start() { |
|
|
|
Impl::Start(); |
|
|
|
} |
|
|
|
|
|
|
|
void DisableLoggingInTests() { |
|
|
|
initialization_in_progress_suppress_logging = true; |
|
|
|
} |
|
|
|
|