2012-08-29 00:32:15 +04:00
|
|
|
#include "event_manager.hh"
|
|
|
|
|
2013-01-10 21:54:40 +04:00
|
|
|
#include <poll.h>
|
2012-08-29 00:32:15 +04:00
|
|
|
|
|
|
|
namespace Kakoune
|
|
|
|
{
|
|
|
|
|
2013-01-10 21:54:40 +04:00
|
|
|
FDWatcher::FDWatcher(int fd, Callback callback)
|
|
|
|
: m_fd{fd}, m_callback{std::move(callback)}
|
2012-12-03 21:49:09 +04:00
|
|
|
{
|
2013-01-31 21:58:25 +04:00
|
|
|
EventManager::instance().m_fd_watchers.insert(this);
|
2012-12-03 21:49:09 +04:00
|
|
|
}
|
|
|
|
|
2013-01-10 21:54:40 +04:00
|
|
|
FDWatcher::~FDWatcher()
|
2012-08-29 00:32:15 +04:00
|
|
|
{
|
2013-01-31 21:58:25 +04:00
|
|
|
EventManager::instance().m_fd_watchers.erase(this);
|
2012-08-29 00:32:15 +04:00
|
|
|
}
|
|
|
|
|
2013-01-14 22:07:38 +04:00
|
|
|
Timer::Timer(TimePoint date, Callback callback)
|
|
|
|
: m_date{date}, m_callback{std::move(callback)}
|
|
|
|
{
|
2014-08-15 02:51:24 +04:00
|
|
|
if (EventManager::has_instance())
|
|
|
|
EventManager::instance().m_timers.insert(this);
|
2013-01-14 22:07:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
Timer::~Timer()
|
|
|
|
{
|
2014-08-15 02:51:24 +04:00
|
|
|
if (EventManager::has_instance())
|
|
|
|
EventManager::instance().m_timers.erase(this);
|
2013-01-14 22:07:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Timer::run()
|
|
|
|
{
|
|
|
|
m_date = TimePoint::max();
|
|
|
|
m_callback(*this);
|
|
|
|
}
|
|
|
|
|
2013-01-10 21:54:40 +04:00
|
|
|
EventManager::EventManager()
|
2012-08-29 00:32:15 +04:00
|
|
|
{
|
2013-01-10 21:54:40 +04:00
|
|
|
m_forced_fd.reserve(4);
|
|
|
|
}
|
2012-11-27 16:57:03 +04:00
|
|
|
|
2013-01-10 21:54:40 +04:00
|
|
|
EventManager::~EventManager()
|
|
|
|
{
|
2013-04-09 22:04:11 +04:00
|
|
|
kak_assert(m_fd_watchers.empty());
|
|
|
|
kak_assert(m_timers.empty());
|
2012-08-29 00:32:15 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void EventManager::handle_next_events()
|
|
|
|
{
|
2013-01-10 21:54:40 +04:00
|
|
|
std::vector<pollfd> events;
|
|
|
|
events.reserve(m_fd_watchers.size());
|
|
|
|
for (auto& watcher : m_fd_watchers)
|
|
|
|
events.emplace_back(pollfd{ watcher->fd(), POLLIN | POLLPRI, 0 });
|
2014-01-30 16:41:34 +04:00
|
|
|
|
|
|
|
TimePoint next_timer = TimePoint::max();
|
|
|
|
for (auto& timer : m_timers)
|
|
|
|
{
|
|
|
|
if (timer->next_date() <= next_timer)
|
|
|
|
next_timer = timer->next_date();
|
|
|
|
}
|
2014-03-18 22:53:35 +04:00
|
|
|
using namespace std::chrono;
|
|
|
|
auto timeout = duration_cast<milliseconds>(next_timer - Clock::now()).count();
|
|
|
|
poll(events.data(), events.size(), timeout < INT_MAX ? (int)timeout : INT_MAX);
|
2014-08-17 18:58:42 +04:00
|
|
|
|
|
|
|
// gather forced fds *after* poll, so that signal handlers can write to
|
|
|
|
// m_forced_fd, interupt poll, and directly be serviced.
|
|
|
|
std::vector<int> forced;
|
|
|
|
std::swap(forced, m_forced_fd);
|
|
|
|
|
2014-11-24 16:49:41 +03:00
|
|
|
for (auto& event : events)
|
2012-11-26 17:08:27 +04:00
|
|
|
{
|
|
|
|
const int fd = event.fd;
|
2012-12-03 21:49:09 +04:00
|
|
|
if (event.revents or contains(forced, fd))
|
2013-01-10 21:54:40 +04:00
|
|
|
{
|
2013-01-11 17:28:13 +04:00
|
|
|
auto it = find_if(m_fd_watchers,
|
|
|
|
[fd](FDWatcher* w) { return w->fd() == fd; });
|
2013-01-10 21:54:40 +04:00
|
|
|
if (it != m_fd_watchers.end())
|
|
|
|
(*it)->run();
|
|
|
|
}
|
2012-11-26 17:08:27 +04:00
|
|
|
}
|
2013-01-14 22:07:38 +04:00
|
|
|
|
|
|
|
TimePoint now = Clock::now();
|
|
|
|
for (auto& timer : m_timers)
|
|
|
|
{
|
|
|
|
if (timer->next_date() <= now)
|
|
|
|
timer->run();
|
|
|
|
}
|
2012-08-29 00:32:15 +04:00
|
|
|
}
|
|
|
|
|
2012-10-27 17:01:13 +04:00
|
|
|
void EventManager::force_signal(int fd)
|
|
|
|
{
|
2013-01-10 21:54:40 +04:00
|
|
|
m_forced_fd.push_back(fd);
|
|
|
|
}
|
2012-10-27 17:01:13 +04:00
|
|
|
|
2012-08-29 00:32:15 +04:00
|
|
|
}
|