diff options
author | Yuqian Yang <crupest@crupest.life> | 2025-09-05 22:08:42 +0800 |
---|---|---|
committer | Yuqian Yang <crupest@crupest.life> | 2025-09-05 22:08:42 +0800 |
commit | 79fda9ada7878afef263f4786fd3967ec6dbfdc7 (patch) | |
tree | 951625d93e73758209381c4da801adfa4807f396 | |
parent | 4c3098be1c5abaed610b8f10216d59829fc107ce (diff) | |
download | cru-79fda9ada7878afef263f4786fd3967ec6dbfdc7.tar.gz cru-79fda9ada7878afef263f4786fd3967ec6dbfdc7.tar.bz2 cru-79fda9ada7878afef263f4786fd3967ec6dbfdc7.zip |
Add ReadTimerPipe.
-rw-r--r-- | include/cru/base/platform/unix/EventLoop.h | 8 | ||||
-rw-r--r-- | include/cru/base/platform/unix/UnixFile.h | 3 | ||||
-rw-r--r-- | src/base/platform/unix/EventLoop.cpp | 32 |
3 files changed, 43 insertions, 0 deletions
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<TimerData> timers_; + UnixFileDescriptor timer_pipe_read_end_; + UnixFileDescriptor timer_pipe_write_end_; + std::optional<int> 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<void()> 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 |