blob: 56b22e248ce9128e43969d75d968dcde796b49fc [file] [log] [blame]
Brian Silverman801d49c2016-03-20 15:50:22 -07001#include "aos/vision/events/epoll_events.h"
2
3#include <string.h>
4#include <sys/types.h>
5#include <sys/socket.h>
6#include <fcntl.h>
7#include <sys/epoll.h>
8
9#include <vector>
10
11#include "aos/common/scoped_fd.h"
12#include "aos/common/logging/logging.h"
13
14namespace aos {
15namespace events {
16
17class EpollLoop::Impl {
18 public:
19 Impl() : epoll_fd_(PCHECK(epoll_create1(0))) {}
20
21 void Add(EpollEvent *event) {
22 struct epoll_event temp_event;
23 temp_event.data.ptr = static_cast<void *>(event);
24 temp_event.events = EPOLLIN;
25 PCHECK(epoll_ctl(epoll_fd(), EPOLL_CTL_ADD, event->fd(), &temp_event));
26 }
27
28 void Run() {
29 while (true) {
30 const int timeout = CalculateTimeout();
31 static constexpr size_t kNumberOfEvents = 64;
32 epoll_event events[kNumberOfEvents];
33 const int number_events = PCHECK(
34 epoll_wait(epoll_fd(), events, kNumberOfEvents, timeout));
35
36 for (int i = 0; i < number_events; i++) {
37 EpollEvent *event =
38 static_cast<EpollEvent *>(events[i].data.ptr);
39 if ((events[i].events & ~(EPOLLIN | EPOLLPRI)) != 0) {
40 LOG(FATAL, "unexpected epoll events set in %x on %d\n",
41 events[i].events, event->fd());
42 }
43 event->ReadEvent();
44 }
45
46 for (EpollWatcher *watcher : watchers_) {
47 watcher->Wake();
48 }
49 }
50 }
51
52 void AddWait(EpollWait *wait) { waits_.push_back(wait); }
53 void AddWatcher(EpollWatcher *watcher) { watchers_.push_back(watcher); }
54
55 int epoll_fd() { return epoll_fd_.get(); }
56
57 private:
58 // Calculates the new timeout value to pass to epoll_wait.
59 int CalculateTimeout() {
60 const ::aos::time::Time now = ::aos::time::Time::Now();
61 int r = -1;
62 for (EpollWait *c : waits_) {
63 const int new_timeout = c->Recalculate(now);
64 if (new_timeout >= 0) {
65 if (r < 0 || new_timeout < r) {
66 r = new_timeout;
67 }
68 }
69 }
70 return r;
71 }
72
73 private:
74 ::aos::ScopedFD epoll_fd_;
75 ::std::vector<EpollWait *> waits_;
76 ::std::vector<EpollWatcher *> watchers_;
77};
78
79EpollLoop::EpollLoop() : impl_(new Impl()) {}
80void EpollLoop::Run() { impl_->Run(); }
81void EpollLoop::Add(EpollEvent *event) { impl_->Add(event); }
82void EpollLoop::AddWait(EpollWait *wait) { impl_->AddWait(wait); }
83void EpollLoop::AddWatcher(EpollWatcher *watcher) {
84 impl_->AddWatcher(watcher);
85}
86
87} // namespace events
88} // namespace aos