dwatch/source/depoll.d

86 lines
2 KiB
D
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module depoll;
import core.sys.linux.epoll;
import core.sys.posix.unistd : close;
import core.stdc.errno : errno, EINTR, EEXIST;
import core.stdc.string : strerror;
import std.string : fromStringz;
import std.exception : enforce;
class Epoll
{
private int epfd_ = -1;
this(int flags = 0)
{
epfd_ = epoll_create1(flags);
enforce(epfd_ >= 0, "epoll_create1: " ~ strerror(errno).fromStringz.idup);
}
~this()
{
if (epfd_ >= 0)
{
close(epfd_);
epfd_ = -1;
}
}
/// Добавление дескриптора с произвольным tag (например, tag=0 для fanotify, tag=pid для pidfd)
void add(int fd, uint tag, uint events = EPOLLIN | EPOLLERR | EPOLLHUP)
{
epoll_event ev;
ev.events = events;
ev.data.u32 = tag;
auto rc = epoll_ctl(epfd_, EPOLL_CTL_ADD, fd, &ev);
if (rc != 0 && errno == EEXIST)
{
// Если уже добавлен — делаем MOD
rc = epoll_ctl(epfd_, EPOLL_CTL_MOD, fd, &ev);
}
enforce(rc == 0, "epoll_ctl ADD/MOD: " ~ strerror(errno).fromStringz.idup);
}
/// Опционально: явное удаление
void remove(int fd)
{
auto rc = epoll_ctl(epfd_, EPOLL_CTL_DEL, fd, null);
enforce(rc == 0, "epoll_ctl DEL: " ~ strerror(errno).fromStringz.idup);
}
struct Event
{
uint tag; // то самое, что передавали в add()
uint events; // EPOLL* биты
}
/// Возвращает события; пустой массив — если таймаут/прерывание
Event[] wait(int maxevents = 16, int timeout = -1)
{
epoll_event[] evs = new epoll_event[maxevents];
int n;
// Терпим EINTR и повторяем
while (true)
{
n = epoll_wait(epfd_, evs.ptr, maxevents, timeout);
if (n < 0 && errno == EINTR)
continue;
break;
}
if (n <= 0)
return [];
Event[] res;
res.reserve(n);
foreach (i; 0 .. n)
{
res ~= Event(evs[i].data.u32, evs[i].events);
}
return res;
}
@property int handle() const
{
return epfd_;
}
}