diff options
author | Yuqian Yang <crupest@crupest.life> | 2025-09-07 21:46:34 +0800 |
---|---|---|
committer | Yuqian Yang <crupest@crupest.life> | 2025-09-07 21:46:34 +0800 |
commit | 8465655ceac8e1f78e4af2224ed8b8839ec4a35e (patch) | |
tree | 265499f3c4a46c06a48082e06210e6dbf416972e /src | |
parent | d36ed6c52f679ad0f9a0e89a4e1d09b763f063b8 (diff) | |
download | cru-8465655ceac8e1f78e4af2224ed8b8839ec4a35e.tar.gz cru-8465655ceac8e1f78e4af2224ed8b8839ec4a35e.tar.bz2 cru-8465655ceac8e1f78e4af2224ed8b8839ec4a35e.zip |
Fix logger stop.
Diffstat (limited to 'src')
-rw-r--r-- | src/base/log/Logger.cpp | 60 | ||||
-rw-r--r-- | src/base/platform/unix/EventLoop.cpp | 33 |
2 files changed, 80 insertions, 13 deletions
diff --git a/src/base/log/Logger.cpp b/src/base/log/Logger.cpp index c195cd87..4332ba75 100644 --- a/src/base/log/Logger.cpp +++ b/src/base/log/Logger.cpp @@ -2,8 +2,11 @@ #include "cru/base/log/StdioLogTarget.h" #include <algorithm> +#include <condition_variable> #include <ctime> #include <format> +#include <memory> +#include <mutex> #ifdef CRU_PLATFORM_WINDOWS #include "cru/base/platform/win/DebugLogTarget.h" @@ -65,18 +68,16 @@ std::string MakeLogFinalMessage(const LogInfo &log_info) { } } // namespace -Logger::Logger() - : log_thread_([this] { - while (true) { - auto log_info = log_queue_.Pull(); - std::lock_guard<std::mutex> lock_guard{target_list_mutex_}; - for (const auto &target : target_list_) { - target->Write(log_info.level, MakeLogFinalMessage(log_info)); - } - } - }) {} +Logger::Logger() : log_stop_(false), log_thread_(&Logger::LogThreadRun, this) {} -Logger::~Logger() { log_thread_.detach(); } +Logger::~Logger() { + { + std::unique_lock lock(log_queue_mutex_); + log_stop_ = true; + log_queue_condition_variable_.notify_one(); + } + log_thread_.join(); +} void Logger::Log(LogInfo log_info) { #ifndef CRU_DEBUG @@ -84,7 +85,41 @@ void Logger::Log(LogInfo log_info) { return; } #endif - log_queue_.Push(std::move(log_info)); + + std::unique_lock lock(log_queue_mutex_); + log_queue_.push_back(std::move(log_info)); + log_queue_condition_variable_.notify_one(); +} +void Logger::LogThreadRun() { + while (true) { + std::list<LogInfo> queue; + bool stop = false; + std::vector<ILogTarget *> target_list; + + { + std::unique_lock lock(log_queue_mutex_); + log_queue_condition_variable_.wait( + lock, [this] { return !log_queue_.empty() || log_stop_; }); + std::swap(queue, log_queue_); + stop = log_stop_; + } + + { + std::lock_guard<std::mutex> lock_guard(target_list_mutex_); + for (const auto &target : target_list_) { + target_list.push_back(target.get()); + } + } + + for (const auto &target : target_list) { + for (auto &log_info : queue) { + target->Write(log_info.level, MakeLogFinalMessage(log_info)); + } + } + + // TODO: Should still wait for queue to be cleared. + if (stop) return; + } } LoggerCppStream::LoggerCppStream(Logger *logger, LogLevel level, @@ -102,4 +137,5 @@ LoggerCppStream LoggerCppStream::WithTag(std::string tag) const { void LoggerCppStream::Consume(std::string_view str) { this->logger_->Log(this->level_, this->tag_, std::string(str)); } + } // namespace cru::log diff --git a/src/base/platform/unix/EventLoop.cpp b/src/base/platform/unix/EventLoop.cpp index 3c645a85..8fe3b7ad 100644 --- a/src/base/platform/unix/EventLoop.cpp +++ b/src/base/platform/unix/EventLoop.cpp @@ -1,5 +1,6 @@ #include "cru/base/platform/unix/EventLoop.h" #include "cru/base/Exception.h" +#include "cru/base/log/Logger.h" #include <poll.h> #include <algorithm> @@ -18,7 +19,11 @@ UnixEventLoop::UnixEventLoop() : timer_tag_(1), polls_(1), poll_actions_(1) { poll_actions_[0] = [](auto _) {}; } +UnixEventLoop::~UnixEventLoop() { CRU_LOG_TAG_DEBUG("Event loop destroyed."); } + int UnixEventLoop::Run() { + CRU_LOG_TAG_DEBUG("Event loop started."); + running_thread_ = std::this_thread::get_id(); while (!exit_code_) { @@ -63,7 +68,12 @@ int UnixEventLoop::Run() { return exit_code_.value(); } -void UnixEventLoop::RequestQuit(int exit_code) {} +void UnixEventLoop::RequestQuit(int exit_code) { + exit_code_ = exit_code; + if (std::this_thread::get_id() != running_thread_) { + SetImmediate([] {}); + } +} int UnixEventLoop::SetTimer(std::function<void()> action, std::chrono::milliseconds timeout, bool repeat) { @@ -91,6 +101,14 @@ int UnixEventLoop::SetTimer(std::function<void()> action, return tag; } +void UnixEventLoop::CancelTimer(int id) { + if (std::this_thread::get_id() == running_thread_) { + RemoveTimer(id); + } else { + SetImmediate([this, id] { RemoveTimer(id); }); + } +} + bool UnixEventLoop::CheckPoll() { auto iter = std::ranges::find_if( polls_, [](const pollfd &poll_fd) { return poll_fd.revents != 0; }); @@ -117,6 +135,8 @@ bool UnixEventLoop::CheckTimer() { return false; } + CRU_LOG_TAG_INFO("A timer is to be executed."); + auto &timer = *iter; if (timer.repeat) { while (timer.timeout <= std::chrono::milliseconds::zero()) { @@ -158,6 +178,17 @@ bool UnixEventLoop::ReadTimerPipe() { timers_.push_back(std::move(*pointer)); delete pointer; + CRU_LOG_TAG_INFO("A timer from pipe is received."); + return true; } + +void UnixEventLoop::RemoveTimer(int id) { + auto iter = std::ranges::find_if( + timers_, [id](const TimerData &timer) { return timer.id == id; }); + if (iter != timers_.cend()) { + timers_.erase(iter); + } +} + } // namespace cru::platform::unix |