aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-09-05 22:08:42 +0800
committerYuqian Yang <crupest@crupest.life>2025-09-05 22:08:42 +0800
commit79fda9ada7878afef263f4786fd3967ec6dbfdc7 (patch)
tree951625d93e73758209381c4da801adfa4807f396
parent4c3098be1c5abaed610b8f10216d59829fc107ce (diff)
downloadcru-79fda9ada7878afef263f4786fd3967ec6dbfdc7.tar.gz
cru-79fda9ada7878afef263f4786fd3967ec6dbfdc7.tar.bz2
cru-79fda9ada7878afef263f4786fd3967ec6dbfdc7.zip
Add ReadTimerPipe.
-rw-r--r--include/cru/base/platform/unix/EventLoop.h8
-rw-r--r--include/cru/base/platform/unix/UnixFile.h3
-rw-r--r--src/base/platform/unix/EventLoop.cpp32
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