blob: 2b7eb76964414e44cf36be11824b1d81d7e21b83 [file] [log] [blame]
Austin Schuh6b6dfa52019-06-12 20:16:20 -07001#ifndef AOS_EVENTS_EPOLL_H_
2#define AOS_EVENTS_EPOLL_H_
3
4#include <fcntl.h>
5#include <sys/epoll.h>
6#include <sys/timerfd.h>
7#include <unistd.h>
Austin Schuh4c839682021-07-21 15:30:44 -07008
Austin Schuh6b6dfa52019-06-12 20:16:20 -07009#include <atomic>
Alex Perrycb7da4b2019-08-28 19:35:56 -070010#include <functional>
Austin Schuh6b6dfa52019-06-12 20:16:20 -070011#include <vector>
12
Austin Schuh6b6dfa52019-06-12 20:16:20 -070013#include "aos/time/time.h"
14
15namespace aos {
16namespace internal {
17
18// Class wrapping up timerfd.
19class TimerFd {
20 public:
21 TimerFd();
Austin Schuhf257f3c2019-10-27 21:00:43 -070022 ~TimerFd();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070023
24 TimerFd(const TimerFd &) = delete;
25 TimerFd &operator=(const TimerFd &) = delete;
26 TimerFd(TimerFd &&) = delete;
27 TimerFd &operator=(TimerFd &&) = delete;
28
29 // Sets the trigger time and repeat for the timerfd.
30 // An interval of 0 results in a single expiration.
31 void SetTime(monotonic_clock::time_point start,
32 monotonic_clock::duration interval);
33
34 // Disarms the timer.
35 void Disable() {
36 // Disarm the timer by feeding zero values
37 SetTime(::aos::monotonic_clock::epoch(), ::aos::monotonic_clock::zero());
38 }
39
Austin Schuhde8a8ff2019-11-30 15:25:36 -080040 // Reads the event. Returns the number of elapsed cycles.
41 uint64_t Read();
Austin Schuh6b6dfa52019-06-12 20:16:20 -070042
43 // Returns the file descriptor associated with the timerfd.
44 int fd() { return fd_; }
45
46 private:
47 int fd_ = -1;
48};
49
50// Class to wrap epoll and call a callback when an event happens.
51class EPoll {
52 public:
53 EPoll();
54 ~EPoll();
55 EPoll(const EPoll &) = delete;
56 EPoll &operator=(const EPoll &) = delete;
57 EPoll(EPoll &&) = delete;
58 EPoll &operator=(EPoll &&) = delete;
59
60 // Runs until Quit() is called.
61 void Run();
62
James Kuszmaulc8e657e2020-12-14 23:49:45 -080063 // Consumes a single epoll event. Blocks indefinitely if block is true, or
64 // does not block at all. Returns true if an event was consumed, and false on
65 // any retryable error or if no events are available. Dies fatally on
66 // non-retryable errors.
67 bool Poll(bool block);
68
Austin Schuh6b6dfa52019-06-12 20:16:20 -070069 // Quits. Async safe.
70 void Quit();
71
Austin Schuh4c839682021-07-21 15:30:44 -070072 // Adds a function which will be called before waiting on the epoll file
73 // descriptor.
Austin Schuh219b7782020-12-21 12:01:40 -080074 void BeforeWait(std::function<void()> function);
75
Austin Schuh6b6dfa52019-06-12 20:16:20 -070076 // Registers a function to be called if the fd becomes readable.
Brian Silverman441591b2020-01-31 17:44:32 -080077 // Only one function may be registered for readability on each fd.
Austin Schuh4c839682021-07-21 15:30:44 -070078 // A fd may be registered exclusively with OnReadable/OnWriteable/OnError OR
79 // OnEvents.
Austin Schuh6b6dfa52019-06-12 20:16:20 -070080 void OnReadable(int fd, ::std::function<void()> function);
81
Austin Schuh603419f2021-04-24 18:15:20 -070082 // Registers a function to be called if the fd reports an error.
83 // Only one function may be registered for errors on each fd.
Austin Schuh4c839682021-07-21 15:30:44 -070084 // A fd may be registered exclusively with OnReadable/OnWriteable/OnError OR
85 // OnEvents.
Austin Schuh603419f2021-04-24 18:15:20 -070086 void OnError(int fd, ::std::function<void()> function);
87
Brian Silverman441591b2020-01-31 17:44:32 -080088 // Registers a function to be called if the fd becomes writeable.
89 // Only one function may be registered for writability on each fd.
Austin Schuh4c839682021-07-21 15:30:44 -070090 // A fd may be registered exclusively with OnReadable/OnWriteable/OnError OR
91 // OnEvents.
Brian Silverman441591b2020-01-31 17:44:32 -080092 void OnWriteable(int fd, ::std::function<void()> function);
93
Austin Schuh4c839682021-07-21 15:30:44 -070094 // Registers a function to be called when the configured events occur on fd.
95 // Which events occur will be passed to the function.
96 // A fd may be registered exclusively with OnReadable/OnWriteable/OnError OR
97 // OnEvents.
98 void OnEvents(int fd, ::std::function<void(uint32_t)> function);
99
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700100 // Removes fd from the event loop.
101 // All Fds must be cleaned up before this class is destroyed.
102 void DeleteFd(int fd);
103
Austin Schuh219b7782020-12-21 12:01:40 -0800104 // Removes a closed fd. When fds are closed, they are automatically
105 // unregistered by the kernel. But we need to clean up any state here.
106 // All Fds must be cleaned up before this class is destroyed.
107 void ForgetClosedFd(int fd);
108
Brian Silverman441591b2020-01-31 17:44:32 -0800109 // Enables calling the existing function registered for fd when it becomes
110 // writeable.
111 void EnableWriteable(int fd) { EnableEvents(fd, kOutEvents); }
112
113 // Disables calling the existing function registered for fd when it becomes
114 // writeable.
115 void DisableWriteable(int fd) { DisableEvents(fd, kOutEvents); }
116
Austin Schuh4c839682021-07-21 15:30:44 -0700117 // Sets the epoll events for the given fd. Be careful using this with
118 // OnReadable/OnWriteable/OnError: enabled events which fire with no handler
119 // registered will result in a crash.
120 void SetEvents(int fd, uint32_t events);
121
122 // Returns whether we're currently running. This changes to false when we
123 // start draining events to finish.
124 bool should_run() const { return run_; }
125
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700126 private:
Brian Silverman441591b2020-01-31 17:44:32 -0800127 // Structure whose pointer should be returned by epoll. Makes looking up the
128 // function fast and easy.
129 struct EventData {
130 EventData(int fd_in) : fd(fd_in) {}
Austin Schuh4c839682021-07-21 15:30:44 -0700131 virtual ~EventData() = default;
132
Brian Silverman441591b2020-01-31 17:44:32 -0800133 // We use pointers to these objects as persistent identifiers, so they can't
134 // be moved.
135 EventData(const EventData &) = delete;
136 EventData &operator=(const EventData &) = delete;
137
Austin Schuh4c839682021-07-21 15:30:44 -0700138 // Calls the appropriate callbacks when events are returned from the kernel.
139 virtual void DoCallbacks(uint32_t events) = 0;
140
Brian Silverman441591b2020-01-31 17:44:32 -0800141 const int fd;
142 uint32_t events = 0;
Austin Schuh4c839682021-07-21 15:30:44 -0700143 };
144
145 struct InOutEventData : public EventData {
146 InOutEventData(int fd) : EventData(fd) {}
147 ~InOutEventData() override = default;
148
Austin Schuh603419f2021-04-24 18:15:20 -0700149 std::function<void()> in_fn, out_fn, err_fn;
Austin Schuh4c839682021-07-21 15:30:44 -0700150
151 void DoCallbacks(uint32_t events) override;
152 };
153
154 struct SingleEventData : public EventData {
155 SingleEventData(int fd) : EventData(fd) {}
156 ~SingleEventData() override = default;
157
158 std::function<void(uint32_t)> fn;
159
160 void DoCallbacks(uint32_t events) override { fn(events); }
Brian Silverman441591b2020-01-31 17:44:32 -0800161 };
162
163 void EnableEvents(int fd, uint32_t events);
164 void DisableEvents(int fd, uint32_t events);
165
166 EventData *GetEventData(int fd);
167
168 void DoEpollCtl(EventData *event_data, uint32_t new_events);
169
170 // TODO(Brian): Figure out a nicer way to handle EPOLLPRI than lumping it in
171 // with input.
172 static constexpr uint32_t kInEvents = EPOLLIN | EPOLLPRI;
173 static constexpr uint32_t kOutEvents = EPOLLOUT;
Austin Schuh603419f2021-04-24 18:15:20 -0700174 static constexpr uint32_t kErrorEvents = EPOLLERR;
Brian Silverman441591b2020-01-31 17:44:32 -0800175
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700176 ::std::atomic<bool> run_{true};
177
178 // Main epoll fd.
179 int epoll_fd_;
180
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700181 ::std::vector<::std::unique_ptr<EventData>> fns_;
182
183 // Pipe pair for handling quit.
184 int quit_signal_fd_;
185 int quit_epoll_fd_;
Austin Schuh219b7782020-12-21 12:01:40 -0800186
187 std::vector<std::function<void()>> before_epoll_wait_functions_;
Austin Schuh6b6dfa52019-06-12 20:16:20 -0700188};
189
190} // namespace internal
191} // namespace aos
192
193#endif // AOS_EVENTS_EPOLL_H_