blob: b0c66fa91eb87e876f18c469671ea66249faf16a [file] [log] [blame]
#include "aos/vision/events/epoll_events.h"
#include <fcntl.h>
#include <string.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <vector>
#include "aos/common/logging/logging.h"
namespace aos {
namespace events {
EpollLoop::EpollLoop() : epoll_fd_(PCHECK(epoll_create1(0))) {}
void EpollLoop::Add(EpollEvent *event) {
event->loop_ = this;
struct epoll_event temp_event;
temp_event.data.ptr = static_cast<void *>(event);
temp_event.events = event->events();
PCHECK(epoll_ctl(epoll_fd(), EPOLL_CTL_ADD, event->fd(), &temp_event));
}
void EpollLoop::Delete(EpollEvent *event) {
event->loop_ = nullptr;
PCHECK(epoll_ctl(epoll_fd(), EPOLL_CTL_DEL, event->fd(), NULL));
}
void EpollLoop::Run() {
while (true) {
const int timeout = CalculateTimeout();
static constexpr size_t kNumberOfEvents = 64;
epoll_event events[kNumberOfEvents];
const int number_events =
PCHECK(epoll_wait(epoll_fd(), events, kNumberOfEvents, timeout));
for (int i = 0; i < number_events; i++) {
static_cast<EpollEvent *>(events[i].data.ptr)->DirectEvent(events[i].events);
}
}
}
void EpollLoop::AddWait(EpollWait *wait) { waits_.push_back(wait); }
// Calculates the new timeout value to pass to epoll_wait.
int EpollLoop::CalculateTimeout() {
const monotonic_clock::time_point monotonic_now = monotonic_clock::now();
int r = -1;
for (EpollWait *c : waits_) {
const int new_timeout = c->Recalculate(monotonic_now);
if (new_timeout >= 0) {
if (r < 0 || new_timeout < r) {
r = new_timeout;
}
}
}
return r;
}
} // namespace events
} // namespace aos