From 79fda9ada7878afef263f4786fd3967ec6dbfdc7 Mon Sep 17 00:00:00 2001 From: Yuqian Yang Date: Fri, 5 Sep 2025 22:08:42 +0800 Subject: Add ReadTimerPipe. --- include/cru/base/platform/unix/EventLoop.h | 8 ++++++++ include/cru/base/platform/unix/UnixFile.h | 3 +++ src/base/platform/unix/EventLoop.cpp | 32 ++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+) diff --git a/include/cru/base/platform/unix/EventLoop.h b/include/cru/base/platform/unix/EventLoop.h index bc2bcbf8..b735ef26 100644 --- a/include/cru/base/platform/unix/EventLoop.h +++ b/include/cru/base/platform/unix/EventLoop.h @@ -84,11 +84,19 @@ class UnixEventLoop : public Object2 { action(std::move(action)) {} }; +private: + bool ReadTimerPipe(); + +private: + std::thread::id running_thread_; std::atomic_int timer_tag_; std::vector timers_; + UnixFileDescriptor timer_pipe_read_end_; + UnixFileDescriptor timer_pipe_write_end_; + std::optional exit_code_; }; diff --git a/include/cru/base/platform/unix/UnixFile.h b/include/cru/base/platform/unix/UnixFile.h index 8ce3249d..a5f1eb81 100644 --- a/include/cru/base/platform/unix/UnixFile.h +++ b/include/cru/base/platform/unix/UnixFile.h @@ -37,6 +37,9 @@ class UnixFileDescriptor { explicit operator bool() const { return this->IsValid(); } operator int() const { return this->GetValue(); } + /** + * If O_NONBLOCK is set and EAGAIN or EWOULDBLOCK is returned, -1 is returned. + */ ssize_t Read(void* buffer, size_t size); void SetFileDescriptorFlags(int flags); diff --git a/src/base/platform/unix/EventLoop.cpp b/src/base/platform/unix/EventLoop.cpp index 337d8a44..0aac4134 100644 --- a/src/base/platform/unix/EventLoop.cpp +++ b/src/base/platform/unix/EventLoop.cpp @@ -37,6 +37,10 @@ int UnixEventLoop::Run() { continue; } + while (ReadTimerPipe()) { + continue; + } + if (!timers_.empty()) { poll_timeout = std::ranges::min_element(timers_, [](const TimerData &left, @@ -89,4 +93,32 @@ int UnixEventLoop::SetTimer(std::function action, return tag; } +bool UnixEventLoop::ReadTimerPipe() { + TimerData *pointer; + constexpr size_t pointer_size = sizeof(decltype(pointer)); + auto rest = pointer_size; + while (true) { + auto result = timer_pipe_read_end_.Read(&pointer, rest); + + if (result == -1) { // If no data. + if (rest == pointer_size) { + return false; + } else { + continue; // Try read again (might spin), as we are in the middle of + // reading a pointer. + } + } + + if (result == 0) { + throw Exception("Unexpected EOF of the timer pipe."); + } + + rest -= result; + } + + timers_.push_back(std::move(*pointer)); + delete pointer; + + return true; +} } // namespace cru::platform::unix -- cgit v1.2.3