blob: aaecdbf7fc54125b35054e9f8b86c17f63fa24aa [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() {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080060 const monotonic_clock::time_point monotonic_now = monotonic_clock::now();
Brian Silverman801d49c2016-03-20 15:50:22 -070061 int r = -1;
62 for (EpollWait *c : waits_) {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080063 const int new_timeout = c->Recalculate(monotonic_now);
Brian Silverman801d49c2016-03-20 15:50:22 -070064 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