2012-08-28 22:32:15 +02:00
|
|
|
#include "event_manager.hh"
|
|
|
|
|
2017-03-15 18:55:34 +01:00
|
|
|
#include "flags.hh"
|
2017-08-29 10:23:03 +02:00
|
|
|
#include "ranges.hh"
|
2014-12-23 14:34:21 +01:00
|
|
|
|
2020-09-18 12:22:25 +02:00
|
|
|
#if defined(__sun__)
|
|
|
|
#include <cstring>
|
|
|
|
#endif
|
|
|
|
|
2014-12-03 14:56:02 +01:00
|
|
|
#include <unistd.h>
|
2012-08-28 22:32:15 +02:00
|
|
|
|
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
2021-03-10 23:02:02 +01:00
|
|
|
FDWatcher::FDWatcher(int fd, FdEvents events, EventMode mode, Callback callback)
|
|
|
|
: m_fd{fd}, m_events{events}, m_mode{mode}, m_callback{std::move(callback)}
|
2012-12-03 18:49:09 +01:00
|
|
|
{
|
2014-12-09 22:59:47 +01:00
|
|
|
EventManager::instance().m_fd_watchers.push_back(this);
|
2012-12-03 18:49:09 +01:00
|
|
|
}
|
|
|
|
|
2013-01-10 18:54:40 +01:00
|
|
|
FDWatcher::~FDWatcher()
|
2012-08-28 22:32:15 +02:00
|
|
|
{
|
2014-12-09 22:59:47 +01:00
|
|
|
unordered_erase(EventManager::instance().m_fd_watchers, this);
|
2012-08-28 22:32:15 +02:00
|
|
|
}
|
|
|
|
|
2016-11-30 14:59:08 +01:00
|
|
|
void FDWatcher::run(FdEvents events, EventMode mode)
|
2014-11-25 02:00:18 +01:00
|
|
|
{
|
2016-11-30 14:59:08 +01:00
|
|
|
m_callback(*this, events, mode);
|
2014-11-25 02:00:18 +01:00
|
|
|
}
|
|
|
|
|
2014-12-03 14:56:02 +01:00
|
|
|
void FDWatcher::close_fd()
|
|
|
|
{
|
2015-06-08 23:42:51 +02:00
|
|
|
if (m_fd != -1)
|
|
|
|
{
|
|
|
|
close(m_fd);
|
|
|
|
m_fd = -1;
|
|
|
|
}
|
2014-12-03 14:56:02 +01:00
|
|
|
}
|
|
|
|
|
2014-11-25 02:00:18 +01:00
|
|
|
Timer::Timer(TimePoint date, Callback callback, EventMode mode)
|
2019-02-09 05:41:09 +01:00
|
|
|
: m_date{date}, m_mode(mode), m_callback{std::move(callback)}
|
2013-01-14 19:07:38 +01:00
|
|
|
{
|
2014-12-19 00:12:58 +01:00
|
|
|
if (m_callback and EventManager::has_instance())
|
2014-12-09 22:59:47 +01:00
|
|
|
EventManager::instance().m_timers.push_back(this);
|
2013-01-14 19:07:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
Timer::~Timer()
|
|
|
|
{
|
2014-12-19 00:12:58 +01:00
|
|
|
if (m_callback and EventManager::has_instance())
|
2014-12-09 22:59:47 +01:00
|
|
|
unordered_erase(EventManager::instance().m_timers, this);
|
2013-01-14 19:07:38 +01:00
|
|
|
}
|
|
|
|
|
2014-11-25 02:00:18 +01:00
|
|
|
void Timer::run(EventMode mode)
|
2013-01-14 19:07:38 +01:00
|
|
|
{
|
2014-12-19 00:12:58 +01:00
|
|
|
kak_assert(m_callback);
|
2014-11-29 21:14:52 +01:00
|
|
|
if (mode == m_mode)
|
2014-11-25 02:00:18 +01:00
|
|
|
{
|
|
|
|
m_date = TimePoint::max();
|
|
|
|
m_callback(*this);
|
|
|
|
}
|
|
|
|
else // try again a little later
|
|
|
|
m_date = Clock::now() + std::chrono::milliseconds{10};
|
2013-01-14 19:07:38 +01:00
|
|
|
}
|
|
|
|
|
2013-01-10 18:54:40 +01:00
|
|
|
EventManager::EventManager()
|
2012-08-28 22:32:15 +02:00
|
|
|
{
|
2014-12-03 14:56:02 +01:00
|
|
|
FD_ZERO(&m_forced_fd);
|
2013-01-10 18:54:40 +01:00
|
|
|
}
|
2012-11-27 13:57:03 +01:00
|
|
|
|
2013-01-10 18:54:40 +01:00
|
|
|
EventManager::~EventManager()
|
|
|
|
{
|
2013-04-09 20:04:11 +02:00
|
|
|
kak_assert(m_fd_watchers.empty());
|
|
|
|
kak_assert(m_timers.empty());
|
2012-08-28 22:32:15 +02:00
|
|
|
}
|
|
|
|
|
2018-05-15 13:37:41 +02:00
|
|
|
bool EventManager::handle_next_events(EventMode mode, sigset_t* sigmask, bool block)
|
2012-08-28 22:32:15 +02:00
|
|
|
{
|
2014-12-03 14:56:02 +01:00
|
|
|
int max_fd = 0;
|
2016-11-30 14:59:08 +01:00
|
|
|
fd_set rfds, wfds, efds;
|
|
|
|
FD_ZERO(&rfds); FD_ZERO(&wfds); FD_ZERO(&efds);
|
2013-01-10 18:54:40 +01:00
|
|
|
for (auto& watcher : m_fd_watchers)
|
2014-12-03 14:56:02 +01:00
|
|
|
{
|
2021-03-10 23:02:02 +01:00
|
|
|
if (watcher->mode() == EventMode::Normal and mode == EventMode::Urgent)
|
|
|
|
continue;
|
|
|
|
|
2014-12-03 14:56:02 +01:00
|
|
|
const int fd = watcher->fd();
|
|
|
|
if (fd != -1)
|
|
|
|
{
|
|
|
|
max_fd = std::max(fd, max_fd);
|
2016-11-30 14:59:08 +01:00
|
|
|
auto events = watcher->events();
|
|
|
|
if (events & FdEvents::Read)
|
|
|
|
FD_SET(fd, &rfds);
|
|
|
|
if (events & FdEvents::Write)
|
|
|
|
FD_SET(fd, &wfds);
|
|
|
|
if (events & FdEvents::Except)
|
|
|
|
FD_SET(fd, &efds);
|
2014-12-03 14:56:02 +01:00
|
|
|
}
|
|
|
|
}
|
2014-01-30 13:41:34 +01:00
|
|
|
|
2014-12-12 14:55:32 +01:00
|
|
|
bool with_timeout = false;
|
2018-06-03 04:04:55 +02:00
|
|
|
if (m_has_forced_fd)
|
|
|
|
block = false;
|
|
|
|
|
2015-06-09 21:28:24 +02:00
|
|
|
timespec ts{};
|
2018-01-21 02:00:40 +01:00
|
|
|
if (block and not m_timers.empty())
|
2014-01-30 13:41:34 +01:00
|
|
|
{
|
2014-12-12 14:55:32 +01:00
|
|
|
auto next_date = (*std::min_element(
|
2014-12-04 21:01:34 +01:00
|
|
|
m_timers.begin(), m_timers.end(), [](Timer* lhs, Timer* rhs) {
|
|
|
|
return lhs->next_date() < rhs->next_date();
|
2014-12-12 14:55:32 +01:00
|
|
|
}))->next_date();
|
|
|
|
|
|
|
|
if (next_date != TimePoint::max())
|
|
|
|
{
|
|
|
|
with_timeout = true;
|
2015-06-09 21:28:24 +02:00
|
|
|
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() };
|
2014-12-12 14:55:32 +01:00
|
|
|
}
|
2014-01-30 13:41:34 +01:00
|
|
|
}
|
2016-11-30 14:59:08 +01:00
|
|
|
int res = pselect(max_fd + 1, &rfds, &wfds, &efds,
|
2018-01-21 02:00:40 +01:00
|
|
|
not block or with_timeout ? &ts : nullptr, sigmask);
|
2014-08-17 16:58:42 +02:00
|
|
|
|
2015-06-09 14:27:51 +02:00
|
|
|
// copy forced fds *after* select, so that signal handlers can write to
|
|
|
|
// m_forced_fd, interupt select, and directly be serviced.
|
2018-06-03 04:04:55 +02:00
|
|
|
m_has_forced_fd = false;
|
2014-12-03 14:56:02 +01:00
|
|
|
fd_set forced = m_forced_fd;
|
|
|
|
FD_ZERO(&m_forced_fd);
|
2014-08-17 16:58:42 +02:00
|
|
|
|
2014-12-03 14:56:02 +01:00
|
|
|
for (int fd = 0; fd < max_fd + 1; ++fd)
|
2012-11-26 14:08:27 +01:00
|
|
|
{
|
2016-11-30 14:59:08 +01:00
|
|
|
auto events = FD_ISSET(fd, &forced) ? FdEvents::Read : FdEvents::None;
|
|
|
|
if (res > 0)
|
|
|
|
events |= (FD_ISSET(fd, &rfds) ? FdEvents::Read : FdEvents::None) |
|
|
|
|
(FD_ISSET(fd, &wfds) ? FdEvents::Write : FdEvents::None) |
|
|
|
|
(FD_ISSET(fd, &efds) ? FdEvents::Except : FdEvents::None);
|
|
|
|
|
|
|
|
if (events != FdEvents::None)
|
2013-01-10 18:54:40 +01:00
|
|
|
{
|
2013-01-11 14:28:13 +01:00
|
|
|
auto it = find_if(m_fd_watchers,
|
2014-12-03 14:56:02 +01:00
|
|
|
[fd](const FDWatcher* w){return w->fd() == fd; });
|
2013-01-10 18:54:40 +01:00
|
|
|
if (it != m_fd_watchers.end())
|
2016-11-30 14:59:08 +01:00
|
|
|
(*it)->run(events, mode);
|
2013-01-10 18:54:40 +01:00
|
|
|
}
|
2012-11-26 14:08:27 +01:00
|
|
|
}
|
2013-01-14 19:07:38 +01:00
|
|
|
|
|
|
|
TimePoint now = Clock::now();
|
2016-12-06 14:55:53 +01:00
|
|
|
auto timers = m_timers; // copy timers in case m_timers gets mutated
|
|
|
|
for (auto& timer : timers)
|
2013-01-14 19:07:38 +01:00
|
|
|
{
|
2016-12-06 14:55:53 +01:00
|
|
|
if (contains(m_timers, timer) and timer->next_date() <= now)
|
2014-11-25 02:00:18 +01:00
|
|
|
timer->run(mode);
|
2013-01-14 19:07:38 +01:00
|
|
|
}
|
2018-05-15 13:37:41 +02:00
|
|
|
|
|
|
|
return res > 0;
|
2012-08-28 22:32:15 +02:00
|
|
|
}
|
|
|
|
|
2012-10-27 15:01:13 +02:00
|
|
|
void EventManager::force_signal(int fd)
|
|
|
|
{
|
2014-12-03 14:56:02 +01:00
|
|
|
FD_SET(fd, &m_forced_fd);
|
2018-06-03 04:04:55 +02:00
|
|
|
m_has_forced_fd = true;
|
2013-01-10 18:54:40 +01:00
|
|
|
}
|
2012-10-27 15:01:13 +02:00
|
|
|
|
2016-01-10 21:46:15 +01:00
|
|
|
SignalHandler set_signal_handler(int signum, SignalHandler handler)
|
2015-12-20 21:27:34 +01:00
|
|
|
{
|
|
|
|
struct sigaction new_action, old_action;
|
|
|
|
|
|
|
|
sigemptyset(&new_action.sa_mask);
|
|
|
|
new_action.sa_handler = handler;
|
|
|
|
new_action.sa_flags = SA_RESTART;
|
|
|
|
sigaction(signum, &new_action, &old_action);
|
|
|
|
return old_action.sa_handler;
|
|
|
|
}
|
2012-08-28 22:32:15 +02:00
|
|
|
}
|