blob: f6cba7616eafbef091050a649c76bccd6f9cc290 [file] [log] [blame]
Brian Silverman801d49c2016-03-20 15:50:22 -07001#include "aos/vision/events/epoll_events.h"
2
Brian Silverman801d49c2016-03-20 15:50:22 -07003#include <fcntl.h>
Parker Schuhb59bf5e2016-12-28 21:09:36 -08004#include <string.h>
Brian Silverman801d49c2016-03-20 15:50:22 -07005#include <sys/epoll.h>
Parker Schuhb59bf5e2016-12-28 21:09:36 -08006#include <sys/socket.h>
7#include <sys/types.h>
Brian Silverman801d49c2016-03-20 15:50:22 -07008#include <vector>
9
John Park33858a32018-09-28 23:05:48 -070010#include "aos/logging/logging.h"
Brian Silverman801d49c2016-03-20 15:50:22 -070011
12namespace aos {
13namespace events {
14
Brian Silverman58899fd2019-03-24 11:03:11 -070015void EpollEvent::DirectEvent(uint32_t events) {
16 if ((events & ~(EPOLLIN | EPOLLPRI | EPOLLERR)) != 0) {
17 LOG(FATAL, "unexpected epoll events set in %x on %d\n", events, fd());
18 }
19 ReadEvent();
20}
21
22void EpollEvent::SetEvents(uint32_t events) {
23 events_ |= events;
24 CHECK(!loop_);
25}
26
Parker Schuhb59bf5e2016-12-28 21:09:36 -080027EpollLoop::EpollLoop() : epoll_fd_(PCHECK(epoll_create1(0))) {}
Brian Silverman801d49c2016-03-20 15:50:22 -070028
Parker Schuhb59bf5e2016-12-28 21:09:36 -080029void EpollLoop::Add(EpollEvent *event) {
30 event->loop_ = this;
31 struct epoll_event temp_event;
32 temp_event.data.ptr = static_cast<void *>(event);
Parker Schuhc1975fc2018-04-07 15:27:07 -070033 temp_event.events = event->events();
Parker Schuhb59bf5e2016-12-28 21:09:36 -080034 PCHECK(epoll_ctl(epoll_fd(), EPOLL_CTL_ADD, event->fd(), &temp_event));
35}
Brian Silverman801d49c2016-03-20 15:50:22 -070036
Parker Schuhb59bf5e2016-12-28 21:09:36 -080037void EpollLoop::Delete(EpollEvent *event) {
Parker Schuhc1975fc2018-04-07 15:27:07 -070038 event->loop_ = nullptr;
Parker Schuhb59bf5e2016-12-28 21:09:36 -080039 PCHECK(epoll_ctl(epoll_fd(), EPOLL_CTL_DEL, event->fd(), NULL));
40}
Brian Silverman801d49c2016-03-20 15:50:22 -070041
Parker Schuhb59bf5e2016-12-28 21:09:36 -080042void EpollLoop::Run() {
43 while (true) {
44 const int timeout = CalculateTimeout();
45 static constexpr size_t kNumberOfEvents = 64;
46 epoll_event events[kNumberOfEvents];
47 const int number_events =
48 PCHECK(epoll_wait(epoll_fd(), events, kNumberOfEvents, timeout));
49
50 for (int i = 0; i < number_events; i++) {
Parker Schuhc1975fc2018-04-07 15:27:07 -070051 static_cast<EpollEvent *>(events[i].data.ptr)->DirectEvent(events[i].events);
Parker Schuhb59bf5e2016-12-28 21:09:36 -080052 }
Brian Silverman801d49c2016-03-20 15:50:22 -070053 }
Parker Schuhb59bf5e2016-12-28 21:09:36 -080054}
Brian Silverman801d49c2016-03-20 15:50:22 -070055
Parker Schuhb59bf5e2016-12-28 21:09:36 -080056void EpollLoop::AddWait(EpollWait *wait) { waits_.push_back(wait); }
Parker Schuhb59bf5e2016-12-28 21:09:36 -080057
58// Calculates the new timeout value to pass to epoll_wait.
59int EpollLoop::CalculateTimeout() {
60 const monotonic_clock::time_point monotonic_now = monotonic_clock::now();
61 int r = -1;
62 for (EpollWait *c : waits_) {
63 const int new_timeout = c->Recalculate(monotonic_now);
64 if (new_timeout >= 0) {
65 if (r < 0 || new_timeout < r) {
66 r = new_timeout;
67 }
68 }
69 }
70 return r;
Brian Silverman801d49c2016-03-20 15:50:22 -070071}
72
73} // namespace events
74} // namespace aos