summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/event_manager.cc25
-rw-r--r--src/event_manager.hh7
-rw-r--r--src/file.cc4
-rw-r--r--src/main.cc8
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&) {}