#pragma once #if !defined(__unix) && !defined(__APPLE__) #error "This file can only be included on unix." #endif #include "../../Base.h" #include "../../Exception.h" #include "UnixFile.h" #include #include #include #include #include #include namespace cru::platform::unix { class UnixTimerFile : public Object2 { public: template explicit UnixTimerFile(std::chrono::duration time) { auto fds = OpenUniDirectionalPipe(); this->read_fd_ = std::move(fds.read); this->write_fd_ = std::move(fds.write); this->thread_ = std::thread([this, time] { std::this_thread::sleep_for(time); constexpr auto buffer = ""; auto written = ::write(this->write_fd_, buffer, 1); if (written != 1) { throw Exception( "Failed to write to pipe in UnixTimerFile thread at timeout."); } }); this->thread_.detach(); } int GetReadFd() const; private: UnixFileDescriptor write_fd_; UnixFileDescriptor read_fd_; std::thread thread_; }; class UnixEventLoop : public Object2 { public: UnixEventLoop(); int Run(); void RequestQuit(int exit_code = 0); int SetTimer(std::function action, std::chrono::milliseconds timeout, bool repeat); int SetImmediate(std::function action) { return this->SetTimer(std::move(action), std::chrono::milliseconds::zero(), false); } int SetTimeout(std::function action, std::chrono::milliseconds timeout) { return this->SetTimer(std::move(action), std::move(timeout), false); } int SetInterval(std::function action, std::chrono::milliseconds interval) { return this->SetTimer(std::move(action), std::move(interval), true); } private: struct TimerData { int id; std::chrono::milliseconds original_timeout; std::chrono::milliseconds timeout; bool repeat; std::function action; TimerData(int id, std::chrono::milliseconds timeout, bool repeat, std::function action) : id(id), original_timeout(timeout), timeout(timeout), repeat(repeat), action(std::move(action)) {} }; private: bool CheckPoll(); bool CheckTimer(); bool ReadTimerPipe(); private: std::thread::id running_thread_; std::vector polls_; std::vector< std::function().revents) revent)>> poll_actions_; std::atomic_int timer_tag_; std::vector timers_; UnixFileDescriptor timer_pipe_read_end_; UnixFileDescriptor timer_pipe_write_end_; std::optional exit_code_; }; } // namespace cru::platform::unix