diff --git a/include/Logger.h b/include/Logger.h index ddea34b7..c8de6ade 100644 --- a/include/Logger.h +++ b/include/Logger.h @@ -8,6 +8,7 @@ #include #include void InitLog(); +void CloseLog(); void except(const std::string& toPrint); void fatal(const std::string& toPrint); void debug(const std::string& toPrint); diff --git a/src/Logger.cpp b/src/Logger.cpp index 771d07d4..ac62b996 100644 --- a/src/Logger.cpp +++ b/src/Logger.cpp @@ -12,7 +12,47 @@ #include #include #include +#include #include "Options.h" +#include +#include +#include + +std::mutex logMutex; +std::condition_variable logCV; +std::queue logQueue; +bool logThreadRunning = false; +std::thread logThread; + +void logThreadFunc() { +#ifdef _WIN32 + std::wofstream LFS; +#else + std::ofstream LFS; +#endif + LFS.open(GetEP() + beammp_wide("Launcher.log"), std::ios_base::out); + if (!LFS.is_open()) { + std::cerr << "Failed to open Launcher.log: " << std::strerror(errno) << std::endl; + return; + } + + while (logThreadRunning || !logQueue.empty()) { + std::unique_lock lock(logMutex); + logCV.wait(lock, [] { return !logQueue.empty() || !logThreadRunning; }); + + while (!logQueue.empty()) { + beammp_fs_string line = logQueue.front(); + logQueue.pop(); + lock.unlock(); + + LFS << line; + LFS.flush(); + + lock.lock(); + } + } + LFS.close(); +} std::string getDate() { time_t tt = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); @@ -36,24 +76,39 @@ std::string getDate() { return date.str(); } void InitLog() { - std::ofstream LFS; - LFS.open(GetEP() + beammp_wide("Launcher.log")); - if (!LFS.is_open()) { - error("logger file init failed!"); - } else - LFS.close(); + logThreadRunning = true; + logThread = std::thread(logThreadFunc); +} +void CloseLog() { + if (logThreadRunning) { + logThreadRunning = false; + logCV.notify_one(); + if (logThread.joinable()) { + logThread.join(); + } + } } void addToLog(const std::string& Line) { - std::ofstream LFS; - LFS.open(GetEP() + beammp_wide("Launcher.log"), std::ios_base::app); - LFS << Line.c_str(); - LFS.close(); + { + std::lock_guard lock(logMutex); +#ifdef _WIN32 + logQueue.push(Utils::ToWString(Line)); +#else + logQueue.push(Line); +#endif + } + logCV.notify_one(); } void addToLog(const std::wstring& Line) { - std::wofstream LFS; - LFS.open(GetEP() + beammp_wide("Launcher.log"), std::ios_base::app); - LFS << Line.c_str(); - LFS.close(); + { + std::lock_guard lock(logMutex); +#ifdef _WIN32 + logQueue.push(Line); +#else + logQueue.push(std::string(Line.begin(), Line.end())); +#endif + } + logCV.notify_one(); } void info(const std::string& toPrint) { std::string Print = getDate() + "[INFO] " + toPrint + "\n"; diff --git a/src/main.cpp b/src/main.cpp index b2f90991..eaf3f53c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -62,9 +62,11 @@ int main(int argc, const char** argv) try { PreGame(GetGameDir()); InitGame(GetGameDir()); CoreNetwork(); + CloseLog(); } catch (const std::exception& e) { error(std::string("Exception in main(): ") + e.what()); info("Closing in 5 seconds"); info("If this keeps happening, contact us on either: Forum: https://forum.beammp.com, Discord: https://discord.gg/beammp"); std::this_thread::sleep_for(std::chrono::seconds(5)); + CloseLog(); }