blob: 1cb684233dd6997e09db4fb0ffb6cc8fcc5872ce [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.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080028 void SetTime(const monotonic_clock::time_point new_time) { time_ = new_time; }
Brian Silverman801d49c2016-03-20 15:50:22 -070029
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.
Austin Schuhf2a50ba2016-12-24 16:16:26 -080036 int Recalculate(const monotonic_clock::time_point now) {
37 if (time_ < monotonic_clock::epoch()) return -1;
Brian Silverman801d49c2016-03-20 15:50:22 -070038 if (time_ <= now) {
39 Done();
Austin Schuhf2a50ba2016-12-24 16:16:26 -080040 time_ = monotonic_clock::time_point(::std::chrono::seconds(-1));
Brian Silverman801d49c2016-03-20 15:50:22 -070041 return -1;
42 }
Austin Schuhf2a50ba2016-12-24 16:16:26 -080043 if (time_ - now > ::std::chrono::milliseconds(INT_MAX)) {
Brian Silverman801d49c2016-03-20 15:50:22 -070044 return INT_MAX;
45 } else {
Austin Schuhf2a50ba2016-12-24 16:16:26 -080046 return ::std::chrono::duration_cast<::std::chrono::milliseconds>(time_ -
47 now)
48 .count();
Brian Silverman801d49c2016-03-20 15:50:22 -070049 }
50 }
51
Austin Schuhf2a50ba2016-12-24 16:16:26 -080052 ::aos::monotonic_clock::time_point time_ = ::aos::monotonic_clock::epoch();
Brian Silverman801d49c2016-03-20 15:50:22 -070053
54 friend class EpollLoop;
55};
56
57// Represents a file descriptor which signals events from an EpollLoop.
58class EpollEvent {
59 public:
60 EpollEvent(int fd) : fd_(fd) {}
61 virtual ~EpollEvent() {}
62
63 int fd() { return fd_; }
64
65 // Called when fd() is readable. This must make fd() non-readable or the event
66 // loop degrades into a busy loop.
67 virtual void ReadEvent() = 0;
68
69 private:
70 const int fd_;
71};
72
73// Provides a way for code to be notified every time after events are handled by
74// an EpollLoop. This is mainly a hack for the GTK integration and testing;
75// think very carefully before using it anywhere else.
76class EpollWatcher {
77 public:
78 virtual ~EpollWatcher() {}
79
80 // Called after events have been processed each time the event loop wakes up.
81 virtual void Wake() = 0;
82};
83
84// A file descriptor based event loop implemented with epoll.
85//
86// There is currently no way to remove events because that's hard
87// (have to deal with events that come in for a file descriptor after it's
88// removed, which means not closing the fd or destroying the object until the
89// epoll mechanism confirms its removal) and we don't have a use for it.
90class EpollLoop {
91 public:
92 EpollLoop();
93
94 // Ways to add various objects which interact with this event loop.
95 // None of these take ownership of the passed-in objects.
96 void AddWait(EpollWait *wait);
97 void Add(EpollEvent *event);
98 void AddWatcher(EpollWatcher *watcher);
99
100 // Loops forever, handling events.
101 void Run();
102
103 private:
104 class Impl;
105
106 ::std::unique_ptr<Impl> impl_;
107};
108
109} // namespace events
110} // namespace aos
111
112#endif // AOS_VISION_EVENTS_EPOLL_EVENTS_H_