aboutsummaryrefslogtreecommitdiff
path: root/src/base
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-09-07 21:46:34 +0800
committerYuqian Yang <crupest@crupest.life>2025-09-07 21:46:34 +0800
commit8465655ceac8e1f78e4af2224ed8b8839ec4a35e (patch)
tree265499f3c4a46c06a48082e06210e6dbf416972e /src/base
parentd36ed6c52f679ad0f9a0e89a4e1d09b763f063b8 (diff)
downloadcru-8465655ceac8e1f78e4af2224ed8b8839ec4a35e.tar.gz
cru-8465655ceac8e1f78e4af2224ed8b8839ec4a35e.tar.bz2
cru-8465655ceac8e1f78e4af2224ed8b8839ec4a35e.zip
Fix logger stop.
Diffstat (limited to 'src/base')
-rw-r--r--src/base/log/Logger.cpp60
-rw-r--r--src/base/platform/unix/EventLoop.cpp33
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