diff options
| -rw-r--r-- | src/event_manager.cc | 25 | ||||
| -rw-r--r-- | src/event_manager.hh | 7 | ||||
| -rw-r--r-- | src/file.cc | 4 | ||||
| -rw-r--r-- | src/main.cc | 8 |
4 files changed, 25 insertions, 19 deletions
diff --git a/src/event_manager.cc b/src/event_manager.cc index ed608fcc..01838de6 100644 --- a/src/event_manager.cc +++ b/src/event_manager.cc @@ -73,7 +73,7 @@ EventManager::~EventManager() kak_assert(m_timers.empty()); } -bool EventManager::handle_next_events(EventMode mode, sigset_t* sigmask, bool block) +bool EventManager::handle_next_events(EventMode mode, sigset_t* sigmask, Optional<Nanoseconds> timeout) { int max_fd = 0; fd_set rfds, wfds, efds; @@ -97,12 +97,10 @@ bool EventManager::handle_next_events(EventMode mode, sigset_t* sigmask, bool bl FD_SET(fd, &efds); } - bool with_timeout = false; if (m_has_forced_fd) - block = false; + timeout.reset(); - timespec ts{}; - if (block and not m_timers.empty()) + if (not m_timers.empty()) { auto next_date = (*std::min_element( m_timers.begin(), m_timers.end(), [](Timer* lhs, Timer* rhs) { @@ -111,15 +109,16 @@ bool EventManager::handle_next_events(EventMode mode, sigset_t* sigmask, bool bl if (next_date != TimePoint::max()) { - with_timeout = true; - using namespace std::chrono; using ns = std::chrono::nanoseconds; - auto nsecs = std::max(ns(0), duration_cast<ns>(next_date - Clock::now())); - auto secs = duration_cast<seconds>(nsecs); - ts = timespec{ (time_t)secs.count(), (long)(nsecs - secs).count() }; + auto remaining = std::max(Nanoseconds(0), + std::chrono::duration_cast<Nanoseconds>(next_date - Clock::now())); + timeout = timeout ? std::min(*timeout, remaining) : remaining; } } - int res = pselect(max_fd + 1, &rfds, &wfds, &efds, - not block or with_timeout ? &ts : nullptr, sigmask); + auto ts = timeout.map([](auto nsecs) { + auto secs = std::chrono::duration_cast<std::chrono::seconds>(nsecs); + return timespec{(time_t)secs.count(), (long)(nsecs - secs).count()}; + }); + int res = pselect(max_fd + 1, &rfds, &wfds, &efds, ts ? &*ts : nullptr, sigmask); // copy forced fds *after* select, so that signal handlers can write to // m_forced_fd, interupt select, and directly be serviced. @@ -164,7 +163,7 @@ void EventManager::force_signal(int fd) void EventManager::handle_urgent_events() { if (has_instance()) - instance().handle_next_events(EventMode::Urgent, nullptr, false); + instance().handle_next_events(EventMode::Urgent, nullptr, Nanoseconds{}); } diff --git a/src/event_manager.hh b/src/event_manager.hh index 68f6dee3..92d90105 100644 --- a/src/event_manager.hh +++ b/src/event_manager.hh @@ -4,6 +4,7 @@ #include "clock.hh" #include "meta.hh" #include "utils.hh" +#include "optional.hh" #include "vector.hh" #include <functional> @@ -87,10 +88,14 @@ private: class EventManager : public Singleton<EventManager> { public: + using Nanoseconds = std::chrono::nanoseconds; + EventManager(); ~EventManager(); - bool handle_next_events(EventMode mode, sigset_t* sigmask = nullptr, bool block = true); + // blocks until next event if no timeout given + bool handle_next_events(EventMode mode, sigset_t* sigmask = nullptr, + Optional<Nanoseconds> timeout = {}); // force the watchers associated with fd to be executed // on next handle_next_events call. diff --git a/src/file.cc b/src/file.cc index f75b0685..262caa09 100644 --- a/src/file.cc +++ b/src/file.cc @@ -269,7 +269,7 @@ void write(int fd, StringView data) count -= written; } else if (errno == EAGAIN and not atomic and EventManager::has_instance()) - EventManager::instance().handle_next_events(EventMode::Urgent, nullptr, false); + EventManager::instance().handle_next_events(EventMode::Urgent, nullptr, std::chrono::nanoseconds{}); else throw file_access_error(format("fd: {}", fd), strerror(errno)); } @@ -285,7 +285,7 @@ void write_to_file(StringView filename, StringView data) while ((fd = open(filename.zstr(), flags, 0644)) == -1) { if (errno == ENXIO and EventManager::has_instance()) // trying to open a FIFO with no readers yet - EventManager::instance().handle_next_events(EventMode::Urgent, nullptr, false); + EventManager::instance().handle_next_events(EventMode::Urgent, nullptr, std::chrono::nanoseconds{1'000'000}); else throw file_access_error(filename, strerror(errno)); } diff --git a/src/main.cc b/src/main.cc index ec2b80bd..a7556905 100644 --- a/src/main.cc +++ b/src/main.cc @@ -908,14 +908,16 @@ int run_server(StringView session, StringView server_init, // Loop so that eventual inputs happening during the processing are handled as // well, avoiding unneeded redraws. - bool allow_blocking = not client_manager.has_pending_inputs(); + Optional<std::chrono::nanoseconds> timeout; + if (client_manager.has_pending_inputs()) + timeout = std::chrono::nanoseconds{}; try { - while (event_manager.handle_next_events(EventMode::Normal, nullptr, allow_blocking)) + while (event_manager.handle_next_events(EventMode::Normal, nullptr, timeout)) { if (client_manager.process_pending_inputs()) break; - allow_blocking = false; + timeout = std::chrono::nanoseconds{}; } } catch (const cancel&) {} |
