blob: bb1d6e39ea9fe033afc7a8791c2d1aca2395d271 [file] [log] [blame]
Alex Perrycb7da4b2019-08-28 19:35:56 -07001#ifndef AOS_EVENTS_EVENT_LOOP_TMPL_H_
2#define AOS_EVENTS_EVENT_LOOP_TMPL_H_
3
Brian Silverman79ec7fc2020-06-08 20:11:22 -05004#include <inttypes.h>
5#include <stdint.h>
6
Alex Perrycb7da4b2019-08-28 19:35:56 -07007#include <type_traits>
Brian Silverman79ec7fc2020-06-08 20:11:22 -05008
Alex Perrycb7da4b2019-08-28 19:35:56 -07009#include "aos/events/event_loop.h"
10#include "glog/logging.h"
11
12namespace aos {
Brian Silverman454bc112020-03-05 14:21:25 -080013namespace event_loop_internal {
Alex Perrycb7da4b2019-08-28 19:35:56 -070014
Brian Silverman454bc112020-03-05 14:21:25 -080015// From a watch functor, specializations of this will extract the message type
16// of the template argument. If T is not a valid message type, there will be no
17// matching specialization.
18//
19// This is just the forward declaration, which will be used by one of the
20// following specializations to match valid argument types.
Alex Perrycb7da4b2019-08-28 19:35:56 -070021template <class T>
Brian Silverman454bc112020-03-05 14:21:25 -080022struct watch_message_type_trait;
Alex Perrycb7da4b2019-08-28 19:35:56 -070023
24// From a watch functor, this will extract the message type of the argument.
25// This is the template specialization.
26template <class ClassType, class ReturnType, class A1>
27struct watch_message_type_trait<ReturnType (ClassType::*)(A1) const> {
28 using message_type = typename std::decay<A1>::type;
29};
30
Brian Silverman454bc112020-03-05 14:21:25 -080031} // namespace event_loop_internal
32
Alex Perrycb7da4b2019-08-28 19:35:56 -070033template <typename T>
34typename Sender<T>::Builder Sender<T>::MakeBuilder() {
Brian Silvermana1652f32020-01-29 20:41:44 -080035 return Builder(sender_.get(), sender_->fbb_allocator());
Alex Perrycb7da4b2019-08-28 19:35:56 -070036}
37
38template <typename Watch>
James Kuszmaul3ae42262019-11-08 12:33:41 -080039void EventLoop::MakeWatcher(const std::string_view channel_name, Watch &&w) {
Brian Silverman454bc112020-03-05 14:21:25 -080040 using MessageType =
41 typename event_loop_internal::watch_message_type_trait<decltype(
42 &Watch::operator())>::message_type;
Alex Perrycb7da4b2019-08-28 19:35:56 -070043 const Channel *channel = configuration::GetChannel(
Brian Silverman454bc112020-03-05 14:21:25 -080044 configuration_, channel_name, MessageType::GetFullyQualifiedName(),
45 name(), node());
Alex Perrycb7da4b2019-08-28 19:35:56 -070046
47 CHECK(channel != nullptr)
48 << ": Channel { \"name\": \"" << channel_name << "\", \"type\": \""
Austin Schuhc59a1de2021-02-20 14:47:39 -080049 << MessageType::GetFullyQualifiedName()
50 << "\" } not found in config for application " << name() << ".";
Alex Perrycb7da4b2019-08-28 19:35:56 -070051
Brian Silverman454bc112020-03-05 14:21:25 -080052 MakeRawWatcher(channel,
53 [this, w](const Context &context, const void *message) {
54 context_ = context;
55 w(*flatbuffers::GetRoot<MessageType>(
56 reinterpret_cast<const char *>(message)));
57 });
58}
59
60template <typename MessageType>
61void EventLoop::MakeNoArgWatcher(const std::string_view channel_name,
62 std::function<void()> w) {
63 const Channel *channel = configuration::GetChannel(
64 configuration_, channel_name, MessageType::GetFullyQualifiedName(),
65 name(), node());
66 CHECK(channel != nullptr)
67 << ": Channel { \"name\": \"" << channel_name << "\", \"type\": \""
Austin Schuhc59a1de2021-02-20 14:47:39 -080068 << MessageType::GetFullyQualifiedName()
69 << "\" } not found in config for application " << name() << ".";
Brian Silverman454bc112020-03-05 14:21:25 -080070 MakeRawNoArgWatcher(channel, [this, w](const Context &context) {
71 context_ = context;
72 w();
73 });
Alex Perrycb7da4b2019-08-28 19:35:56 -070074}
75
Austin Schuh39788ff2019-12-01 18:22:57 -080076inline bool RawFetcher::FetchNext() {
77 const auto result = DoFetchNext();
78 if (result.first) {
79 timing_.fetcher->mutate_count(timing_.fetcher->count() + 1);
80 const monotonic_clock::time_point monotonic_time = result.second;
Brian Silverman79ec7fc2020-06-08 20:11:22 -050081 ftrace_.FormatMessage(
82 "%.*s: fetch next: now=%" PRId64 " event=%" PRId64 " queue=%" PRIu32,
83 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
84 static_cast<int64_t>(monotonic_time.time_since_epoch().count()),
85 static_cast<int64_t>(
86 context_.monotonic_event_time.time_since_epoch().count()),
87 context_.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -080088 const float latency =
89 std::chrono::duration_cast<std::chrono::duration<float>>(
Austin Schuhad154822019-12-27 15:45:13 -080090 monotonic_time - context_.monotonic_event_time)
Austin Schuh39788ff2019-12-01 18:22:57 -080091 .count();
92 timing_.latency.Add(latency);
93 return true;
94 }
Brian Silverman79ec7fc2020-06-08 20:11:22 -050095 ftrace_.FormatMessage(
96 "%.*s: fetch next: still event=%" PRId64 " queue=%" PRIu32,
97 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
98 static_cast<int64_t>(
99 context_.monotonic_event_time.time_since_epoch().count()),
100 context_.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -0800101 return false;
102}
103
104inline bool RawFetcher::Fetch() {
105 const auto result = DoFetch();
106 if (result.first) {
107 timing_.fetcher->mutate_count(timing_.fetcher->count() + 1);
108 const monotonic_clock::time_point monotonic_time = result.second;
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500109 ftrace_.FormatMessage(
110 "%.*s: fetch latest: now=%" PRId64 " event=%" PRId64 " queue=%" PRIu32,
111 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
112 static_cast<int64_t>(monotonic_time.time_since_epoch().count()),
113 static_cast<int64_t>(
114 context_.monotonic_event_time.time_since_epoch().count()),
115 context_.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -0800116 const float latency =
117 std::chrono::duration_cast<std::chrono::duration<float>>(
Austin Schuhad154822019-12-27 15:45:13 -0800118 monotonic_time - context_.monotonic_event_time)
Austin Schuh39788ff2019-12-01 18:22:57 -0800119 .count();
120 timing_.latency.Add(latency);
121 return true;
122 }
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500123 ftrace_.FormatMessage(
124 "%.*s: fetch latest: still event=%" PRId64 " queue=%" PRIu32,
125 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
126 static_cast<int64_t>(
127 context_.monotonic_event_time.time_since_epoch().count()),
128 context_.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -0800129 return false;
130}
131
Austin Schuhb5c6f972021-03-14 21:53:07 -0700132inline bool RawSender::Send(size_t size) {
133 return Send(size, monotonic_clock::min_time, realtime_clock::min_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700134 0xffffffffu, event_loop_->boot_uuid());
Austin Schuhb5c6f972021-03-14 21:53:07 -0700135}
136
Austin Schuhad154822019-12-27 15:45:13 -0800137inline bool RawSender::Send(
138 size_t size, aos::monotonic_clock::time_point monotonic_remote_time,
139 aos::realtime_clock::time_point realtime_remote_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700140 uint32_t remote_queue_index, const UUID &uuid) {
Austin Schuhad154822019-12-27 15:45:13 -0800141 if (DoSend(size, monotonic_remote_time, realtime_remote_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700142 remote_queue_index, uuid)) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800143 timing_.size.Add(size);
144 timing_.sender->mutate_count(timing_.sender->count() + 1);
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500145 ftrace_.FormatMessage(
146 "%.*s: sent internal: event=%" PRId64 " queue=%" PRIu32,
147 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
148 static_cast<int64_t>(monotonic_sent_time().time_since_epoch().count()),
149 sent_queue_index());
Austin Schuh39788ff2019-12-01 18:22:57 -0800150 return true;
151 }
152 return false;
153}
154
Austin Schuhb5c6f972021-03-14 21:53:07 -0700155inline bool RawSender::Send(const void *data, size_t size) {
156 return Send(data, size, monotonic_clock::min_time, realtime_clock::min_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700157 0xffffffffu, event_loop_->boot_uuid());
Austin Schuhb5c6f972021-03-14 21:53:07 -0700158}
159
Austin Schuhad154822019-12-27 15:45:13 -0800160inline bool RawSender::Send(
161 const void *data, size_t size,
162 aos::monotonic_clock::time_point monotonic_remote_time,
163 aos::realtime_clock::time_point realtime_remote_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700164 uint32_t remote_queue_index, const UUID &uuid) {
Austin Schuhad154822019-12-27 15:45:13 -0800165 if (DoSend(data, size, monotonic_remote_time, realtime_remote_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700166 remote_queue_index, uuid)) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800167 timing_.size.Add(size);
168 timing_.sender->mutate_count(timing_.sender->count() + 1);
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500169 ftrace_.FormatMessage(
170 "%.*s: sent external: event=%" PRId64 " queue=%" PRIu32,
171 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
172 static_cast<int64_t>(monotonic_sent_time().time_since_epoch().count()),
173 sent_queue_index());
Austin Schuh39788ff2019-12-01 18:22:57 -0800174 return true;
175 }
176 return false;
177}
178
Austin Schuhcde39fd2020-02-22 20:58:24 -0800179inline monotonic_clock::time_point TimerHandler::Call(
Austin Schuh39788ff2019-12-01 18:22:57 -0800180 std::function<monotonic_clock::time_point()> get_time,
181 monotonic_clock::time_point event_time) {
182 CHECK_NOTNULL(timing_.timer);
183 const monotonic_clock::time_point monotonic_start_time = get_time();
184
Austin Schuhad154822019-12-27 15:45:13 -0800185 event_loop_->context_.monotonic_event_time = event_time;
186 event_loop_->context_.monotonic_remote_time = monotonic_clock::min_time;
187 event_loop_->context_.realtime_remote_time =
188 event_loop_->context_.realtime_event_time = realtime_clock::min_time;
Austin Schuh39788ff2019-12-01 18:22:57 -0800189 event_loop_->context_.queue_index = 0xffffffffu;
190 event_loop_->context_.size = 0;
191 event_loop_->context_.data = nullptr;
Brian Silverman4f4e0612020-08-12 19:54:41 -0700192 event_loop_->context_.buffer_index = -1;
Austin Schuh8902fa52021-03-14 22:39:24 -0700193 event_loop_->context_.remote_boot_uuid = event_loop_->boot_uuid();
Austin Schuh39788ff2019-12-01 18:22:57 -0800194
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500195 ftrace_.FormatMessage(
196 "timer: %.*s: start now=%" PRId64 " event=%" PRId64,
197 static_cast<int>(name_.size()), name_.data(),
198 static_cast<int64_t>(monotonic_start_time.time_since_epoch().count()),
199 static_cast<int64_t>(event_time.time_since_epoch().count()));
Austin Schuh39788ff2019-12-01 18:22:57 -0800200 {
201 const float start_latency =
202 std::chrono::duration_cast<std::chrono::duration<float>>(
203 monotonic_start_time - event_time)
204 .count();
205 timing_.wakeup_latency.Add(start_latency);
206 }
207 timing_.timer->mutate_count(timing_.timer->count() + 1);
208 fn_();
209
210 const monotonic_clock::time_point monotonic_end_time = get_time();
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500211 ftrace_.FormatMessage(
212 "timer: %.*s: end now=%" PRId64, static_cast<int>(name_.size()),
213 name_.data(),
214 static_cast<int64_t>(monotonic_end_time.time_since_epoch().count()));
Austin Schuh39788ff2019-12-01 18:22:57 -0800215
216 const float handler_latency =
217 std::chrono::duration_cast<std::chrono::duration<float>>(
218 monotonic_end_time - monotonic_start_time)
219 .count();
220 timing_.handler_time.Add(handler_latency);
Austin Schuhcde39fd2020-02-22 20:58:24 -0800221 return monotonic_start_time;
Austin Schuh39788ff2019-12-01 18:22:57 -0800222}
223
224inline void PhasedLoopHandler::Call(
225 std::function<monotonic_clock::time_point()> get_time,
226 std::function<void(monotonic_clock::time_point)> schedule) {
227 // Read time directly to save a vtable indirection...
228 const monotonic_clock::time_point monotonic_start_time = get_time();
229
230 // Update the context to hold the desired wakeup time.
Austin Schuhad154822019-12-27 15:45:13 -0800231 event_loop_->context_.monotonic_event_time = phased_loop_.sleep_time();
232 event_loop_->context_.monotonic_remote_time = monotonic_clock::min_time;
233 event_loop_->context_.realtime_remote_time =
234 event_loop_->context_.realtime_event_time = realtime_clock::min_time;
Austin Schuh39788ff2019-12-01 18:22:57 -0800235 event_loop_->context_.queue_index = 0xffffffffu;
236 event_loop_->context_.size = 0;
237 event_loop_->context_.data = nullptr;
Brian Silverman4f4e0612020-08-12 19:54:41 -0700238 event_loop_->context_.buffer_index = -1;
Austin Schuh8902fa52021-03-14 22:39:24 -0700239 event_loop_->context_.remote_boot_uuid = event_loop_->boot_uuid();
Austin Schuh39788ff2019-12-01 18:22:57 -0800240
241 // Compute how many cycles elapsed and schedule the next wakeup.
242 Reschedule(schedule, monotonic_start_time);
243
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500244 ftrace_.FormatMessage(
245 "phased: %.*s: start now=%" PRId64 " event=%" PRId64 " cycles=%d",
246 static_cast<int>(name_.size()), name_.data(),
247 static_cast<int64_t>(monotonic_start_time.time_since_epoch().count()),
248 static_cast<int64_t>(
249 phased_loop_.sleep_time().time_since_epoch().count()),
250 cycles_elapsed_);
Austin Schuh39788ff2019-12-01 18:22:57 -0800251 {
252 const float start_latency =
253 std::chrono::duration_cast<std::chrono::duration<float>>(
Austin Schuhad154822019-12-27 15:45:13 -0800254 monotonic_start_time - event_loop_->context_.monotonic_event_time)
Austin Schuh39788ff2019-12-01 18:22:57 -0800255 .count();
256 timing_.wakeup_latency.Add(start_latency);
257 }
258 timing_.timer->mutate_count(timing_.timer->count() + 1);
259
260 // Call the function with the elapsed cycles.
261 fn_(cycles_elapsed_);
262 cycles_elapsed_ = 0;
263
264 const monotonic_clock::time_point monotonic_end_time = get_time();
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500265 ftrace_.FormatMessage(
266 "phased: %.*s: end now=%" PRId64, static_cast<int>(name_.size()),
267 name_.data(),
268 static_cast<int64_t>(monotonic_end_time.time_since_epoch().count()));
Austin Schuh39788ff2019-12-01 18:22:57 -0800269
270 const float handler_latency =
271 std::chrono::duration_cast<std::chrono::duration<float>>(
272 monotonic_end_time - monotonic_start_time)
273 .count();
274 timing_.handler_time.Add(handler_latency);
275
Brian Silvermanaf9a4d82020-10-06 15:10:58 -0700276 // If the handler took too long so we blew by the previous deadline, we
Austin Schuh91ba6392020-10-03 13:27:47 -0700277 // want to just try for the next deadline. Reschedule.
Austin Schuh39788ff2019-12-01 18:22:57 -0800278 if (monotonic_end_time > phased_loop_.sleep_time()) {
279 Reschedule(schedule, monotonic_end_time);
280 }
281}
282
283// Class to automate the timing report generation for watchers.
284class WatcherState {
285 public:
286 WatcherState(
287 EventLoop *event_loop, const Channel *channel,
288 std::function<void(const Context &context, const void *message)> fn)
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500289 : channel_index_(event_loop->ChannelIndex(channel)),
290 ftrace_prefix_(configuration::StrippedChannelToString(channel)),
291 fn_(std::move(fn)) {}
Austin Schuh39788ff2019-12-01 18:22:57 -0800292
293 virtual ~WatcherState() {}
294
295 // Calls the callback, measuring time with get_time, with the provided
296 // context.
297 void DoCallCallback(std::function<monotonic_clock::time_point()> get_time,
Austin Schuhc5dc98f2021-06-16 14:52:46 -0700298 Context context) noexcept {
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800299 if (context.data) {
300 CheckChannelDataAlignment(context.data, context.size);
301 }
Austin Schuh39788ff2019-12-01 18:22:57 -0800302 const monotonic_clock::time_point monotonic_start_time = get_time();
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500303 ftrace_.FormatMessage(
304 "%.*s: watcher start: now=%" PRId64 " event=%" PRId64 " queue=%" PRIu32,
305 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
306 static_cast<int64_t>(monotonic_start_time.time_since_epoch().count()),
307 static_cast<int64_t>(
308 context.monotonic_event_time.time_since_epoch().count()),
309 context.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -0800310 {
311 const float start_latency =
312 std::chrono::duration_cast<std::chrono::duration<float>>(
Austin Schuhad154822019-12-27 15:45:13 -0800313 monotonic_start_time - context.monotonic_event_time)
Austin Schuh39788ff2019-12-01 18:22:57 -0800314 .count();
315 wakeup_latency_.Add(start_latency);
316 }
317 watcher_->mutate_count(watcher_->count() + 1);
318 fn_(context, context.data);
319
320 const monotonic_clock::time_point monotonic_end_time = get_time();
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500321 ftrace_.FormatMessage(
322 "%.*s: watcher end: now=%" PRId64,
323 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
324 static_cast<int64_t>(monotonic_end_time.time_since_epoch().count()));
Austin Schuh39788ff2019-12-01 18:22:57 -0800325
326 const float handler_latency =
327 std::chrono::duration_cast<std::chrono::duration<float>>(
328 monotonic_end_time - monotonic_start_time)
329 .count();
330 handler_time_.Add(handler_latency);
331 }
332
333 int channel_index() const { return channel_index_; }
334
335 void set_timing_report(timing::Watcher *watcher);
336 void ResetReport();
337
338 virtual void Startup(EventLoop *event_loop) = 0;
339
340 protected:
341 const int channel_index_;
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500342 const std::string ftrace_prefix_;
Austin Schuh39788ff2019-12-01 18:22:57 -0800343
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500344 const std::function<void(const Context &context, const void *message)> fn_;
Austin Schuh39788ff2019-12-01 18:22:57 -0800345
346 internal::TimingStatistic wakeup_latency_;
347 internal::TimingStatistic handler_time_;
348 timing::Watcher *watcher_ = nullptr;
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500349
350 Ftrace ftrace_;
Austin Schuh39788ff2019-12-01 18:22:57 -0800351};
352
Austin Schuha28cbc32019-12-27 16:28:04 -0800353template <typename T>
Austin Schuhadd6eb32020-11-09 21:24:26 -0800354bool Sender<T>::Send(const NonSizePrefixedFlatbuffer<T> &flatbuffer) {
355 return sender_->Send(flatbuffer.span().data(), flatbuffer.span().size());
Austin Schuha28cbc32019-12-27 16:28:04 -0800356}
357
Brian Silverman341b57e2020-06-23 16:23:18 -0700358template <typename T>
359bool Sender<T>::SendDetached(FlatbufferDetachedBuffer<T> detached) {
Austin Schuhadd6eb32020-11-09 21:24:26 -0800360 CHECK_EQ(static_cast<void *>(detached.span().data() + detached.span().size() -
361 sender_->size()),
362 sender_->data())
Brian Silverman341b57e2020-06-23 16:23:18 -0700363 << ": May only send the buffer detached from this Sender";
Austin Schuhadd6eb32020-11-09 21:24:26 -0800364 return sender_->Send(detached.span().size());
Brian Silverman341b57e2020-06-23 16:23:18 -0700365}
366
Alex Perrycb7da4b2019-08-28 19:35:56 -0700367} // namespace aos
368
369#endif // AOS_EVENTS_EVENT_LOOP_TMPL_H