blob: f032e6147d2badf9eaf137917868ca53d77fa637 [file] [log] [blame]
Brian Silverman801d49c2016-03-20 15:50:22 -07001#ifndef AOS_VISION_EVENTS_EPOLL_EVENTS_H_
2#define AOS_VISION_EVENTS_EPOLL_EVENTS_H_
3
4#include <stdint.h>
5#include <limits.h>
6
7#include <memory>
8
9#include "aos/common/time.h"
10
11namespace aos {
12namespace events {
13
14class EpollLoop;
15
16// Performs an asychronous wait using an EpollLoop.
17//
18// Note: this does not have very high resolution (sub-millisecond).
19class EpollWait {
20 public:
21 virtual ~EpollWait() {}
22
23 // Called when the currently set time is reached.
24 virtual void Done() = 0;
25
26 // Sets this wait to end at new_time.
27 // A negative new_time disables this wait.
28 void SetTime(const ::aos::time::Time &new_time) { time_ = new_time; }
29
30 private:
31 // Calculates how long to wait starting at now and calls Done() if
32 // appropriate.
33 // Returns the number of milliseconds from now that this event will expire in.
34 // Returns -1 if this wait is never going to expire.
35 // Returns INT_MAX if this wait expires in longer than that.
36 int Recalculate(const ::aos::time::Time &now) {
37 if (time_ < ::aos::time::Time::kZero) return -1;
38 if (time_ <= now) {
39 Done();
40 time_ = ::aos::time::Time(-1, 0);
41 return -1;
42 }
43 if (time_ - now > ::aos::time::Time::InMS(INT_MAX)) {
44 return INT_MAX;
45 } else {
46 return (time_ - now).ToMSec();
47 }
48 }
49
50 ::aos::time::Time time_ = ::aos::time::Time::kZero;
51
52 friend class EpollLoop;
53};
54
55// Represents a file descriptor which signals events from an EpollLoop.
56class EpollEvent {
57 public:
58 EpollEvent(int fd) : fd_(fd) {}
59 virtual ~EpollEvent() {}
60
61 int fd() { return fd_; }
62
63 // Called when fd() is readable. This must make fd() non-readable or the event
64 // loop degrades into a busy loop.
65 virtual void ReadEvent() = 0;
66
67 private:
68 const int fd_;
69};
70
71// Provides a way for code to be notified every time after events are handled by
72// an EpollLoop. This is mainly a hack for the GTK integration and testing;
73// think very carefully before using it anywhere else.
74class EpollWatcher {
75 public:
76 virtual ~EpollWatcher() {}
77
78 // Called after events have been processed each time the event loop wakes up.
79 virtual void Wake() = 0;
80};
81
82// A file descriptor based event loop implemented with epoll.
83//
84// There is currently no way to remove events because that's hard
85// (have to deal with events that come in for a file descriptor after it's
86// removed, which means not closing the fd or destroying the object until the
87// epoll mechanism confirms its removal) and we don't have a use for it.
88class EpollLoop {
89 public:
90 EpollLoop();
91
92 // Ways to add various objects which interact with this event loop.
93 // None of these take ownership of the passed-in objects.
94 void AddWait(EpollWait *wait);
95 void Add(EpollEvent *event);
96 void AddWatcher(EpollWatcher *watcher);
97
98 // Loops forever, handling events.
99 void Run();
100
101 private:
102 class Impl;
103
104 ::std::unique_ptr<Impl> impl_;
105};
106
107} // namespace events
108} // namespace aos
109
110#endif // AOS_VISION_EVENTS_EPOLL_EVENTS_H_