86 lines
2 KiB
D
86 lines
2 KiB
D
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_;
|
||
}
|
||
}
|