aboutsummaryrefslogtreecommitdiff
path: root/src/base/platform
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-09-05 23:52:33 +0800
committerYuqian Yang <crupest@crupest.life>2025-09-05 23:52:33 +0800
commit227118866190a7fe17b42e8c589c475781c69f33 (patch)
tree0f97183ebc7de6c8e00771ce3957f4b08d5bb012 /src/base/platform
parent79fda9ada7878afef263f4786fd3967ec6dbfdc7 (diff)
downloadcru-227118866190a7fe17b42e8c589c475781c69f33.tar.gz
cru-227118866190a7fe17b42e8c589c475781c69f33.tar.bz2
cru-227118866190a7fe17b42e8c589c475781c69f33.zip
Event loop poll.
Diffstat (limited to 'src/base/platform')
-rw-r--r--src/base/platform/unix/EventLoop.cpp83
-rw-r--r--src/base/platform/unix/UnixFile.cpp13
2 files changed, 74 insertions, 22 deletions
diff --git a/src/base/platform/unix/EventLoop.cpp b/src/base/platform/unix/EventLoop.cpp
index 0aac4134..3c645a85 100644
--- a/src/base/platform/unix/EventLoop.cpp
+++ b/src/base/platform/unix/EventLoop.cpp
@@ -9,31 +9,26 @@
namespace cru::platform::unix {
int UnixTimerFile::GetReadFd() const { return this->read_fd_; }
-UnixEventLoop::UnixEventLoop() : timer_tag_(1) {}
+UnixEventLoop::UnixEventLoop() : timer_tag_(1), polls_(1), poll_actions_(1) {
+ auto timer_pipe = OpenUniDirectionalPipe(UnixPipeFlags::NonBlock);
+ timer_pipe_read_end_ = std::move(timer_pipe.read);
+ timer_pipe_write_end_ = std::move(timer_pipe.write);
+ polls_[0].fd = timer_pipe_read_end_;
+ polls_[0].events = POLLIN;
+ poll_actions_[0] = [](auto _) {};
+}
int UnixEventLoop::Run() {
running_thread_ = std::this_thread::get_id();
- pollfd poll_fds[1];
-
while (!exit_code_) {
int poll_timeout = -1;
- auto iter = std::ranges::find_if(timers_, [](const TimerData &timer) {
- return timer.timeout <= std::chrono::milliseconds::zero();
- });
- if (iter != timers_.end()) {
- auto &timer = *iter;
- if (timer.repeat) {
- while (timer.timeout <= std::chrono::milliseconds::zero()) {
- timer.timeout += timer.original_timeout;
- timer.action();
- }
- } else {
- auto action = timer.action;
- timers_.erase(iter);
- action();
- }
+ while (CheckPoll()) {
+ continue;
+ }
+
+ while (CheckTimer()) {
continue;
}
@@ -51,9 +46,10 @@ int UnixEventLoop::Run() {
auto start = std::chrono::steady_clock::now();
- ::poll(poll_fds, sizeof poll_fds / sizeof *poll_fds, poll_timeout);
-
- // TODO: A Big Implement to handle X events.
+ auto result = ::poll(polls_.data(), polls_.size(), poll_timeout);
+ if (result < 0) {
+ throw Exception("Failed to poll in event loop.");
+ }
auto end = std::chrono::steady_clock::now();
auto time =
@@ -87,12 +83,55 @@ int UnixEventLoop::SetTimer(std::function<void()> action,
timers_.push_back(
TimerData(tag, std::move(timeout), repeat, std::move(action)));
} else {
- // TODO: Implement
+ auto timer =
+ new TimerData(tag, std::move(timeout), repeat, std::move(action));
+ timer_pipe_write_end_.Write(&timer, sizeof(decltype(timer)));
}
return tag;
}
+bool UnixEventLoop::CheckPoll() {
+ auto iter = std::ranges::find_if(
+ polls_, [](const pollfd &poll_fd) { return poll_fd.revents != 0; });
+
+ if (iter == polls_.cend()) {
+ return false;
+ }
+
+ auto &revents = iter->revents;
+ if (revents != 0) {
+ poll_actions_[iter - polls_.cbegin()](revents);
+ }
+ revents = 0;
+
+ return true;
+}
+
+bool UnixEventLoop::CheckTimer() {
+ auto iter = std::ranges::find_if(timers_, [](const TimerData &timer) {
+ return timer.timeout <= std::chrono::milliseconds::zero();
+ });
+
+ if (iter == timers_.end()) {
+ return false;
+ }
+
+ auto &timer = *iter;
+ if (timer.repeat) {
+ while (timer.timeout <= std::chrono::milliseconds::zero()) {
+ timer.timeout += timer.original_timeout;
+ timer.action();
+ }
+ } else {
+ auto action = timer.action;
+ timers_.erase(iter);
+ action();
+ }
+
+ return true;
+}
+
bool UnixEventLoop::ReadTimerPipe() {
TimerData *pointer;
constexpr size_t pointer_size = sizeof(decltype(pointer));
diff --git a/src/base/platform/unix/UnixFile.cpp b/src/base/platform/unix/UnixFile.cpp
index 6d2dea89..9d4db949 100644
--- a/src/base/platform/unix/UnixFile.cpp
+++ b/src/base/platform/unix/UnixFile.cpp
@@ -96,6 +96,19 @@ ssize_t UnixFileDescriptor::Read(void* buffer, size_t size) {
return result;
}
+ssize_t UnixFileDescriptor::Write(const void* buffer, size_t size) {
+ EnsureValid();
+ auto result = ::write(GetValue(), buffer, size);
+ if (result == -1) {
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ return -1;
+ } else {
+ throw ErrnoException("Failed to write on file descriptor.");
+ }
+ }
+ return result;
+}
+
void UnixFileDescriptor::SetFileDescriptorFlags(int flags) {
EnsureValid();
if (::fcntl(GetValue(), F_SETFL, flags) == -1) {