blob: cc8e5c3d4bc4b13f3355ace9d16b33cc4e259d6e [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
Tyler Chatowbf0609c2021-07-31 16:13:27 -07004#include <cinttypes>
5#include <cstdint>
Alex Perrycb7da4b2019-08-28 19:35:56 -07006#include <type_traits>
Brian Silverman79ec7fc2020-06-08 20:11:22 -05007
Alex Perrycb7da4b2019-08-28 19:35:56 -07008#include "glog/logging.h"
9
Philipp Schrader790cb542023-07-05 21:06:52 -070010#include "aos/events/event_loop.h"
11
Alex Perrycb7da4b2019-08-28 19:35:56 -070012namespace 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) {
Philipp Schrader790cb542023-07-05 21:06:52 -070040 using MessageType = typename event_loop_internal::watch_message_type_trait<
41 decltype(&Watch::operator())>::message_type;
Alex Perrycb7da4b2019-08-28 19:35:56 -070042 const Channel *channel = configuration::GetChannel(
Brian Silverman454bc112020-03-05 14:21:25 -080043 configuration_, channel_name, MessageType::GetFullyQualifiedName(),
44 name(), node());
Alex Perrycb7da4b2019-08-28 19:35:56 -070045
46 CHECK(channel != nullptr)
47 << ": Channel { \"name\": \"" << channel_name << "\", \"type\": \""
Austin Schuhc59a1de2021-02-20 14:47:39 -080048 << MessageType::GetFullyQualifiedName()
49 << "\" } not found in config for application " << name() << ".";
Alex Perrycb7da4b2019-08-28 19:35:56 -070050
Brian Silverman454bc112020-03-05 14:21:25 -080051 MakeRawWatcher(channel,
52 [this, w](const Context &context, const void *message) {
53 context_ = context;
54 w(*flatbuffers::GetRoot<MessageType>(
55 reinterpret_cast<const char *>(message)));
56 });
57}
58
59template <typename MessageType>
60void EventLoop::MakeNoArgWatcher(const std::string_view channel_name,
61 std::function<void()> w) {
62 const Channel *channel = configuration::GetChannel(
63 configuration_, channel_name, MessageType::GetFullyQualifiedName(),
64 name(), node());
65 CHECK(channel != nullptr)
66 << ": Channel { \"name\": \"" << channel_name << "\", \"type\": \""
Austin Schuhc59a1de2021-02-20 14:47:39 -080067 << MessageType::GetFullyQualifiedName()
68 << "\" } not found in config for application " << name() << ".";
Brian Silverman454bc112020-03-05 14:21:25 -080069 MakeRawNoArgWatcher(channel, [this, w](const Context &context) {
70 context_ = context;
71 w();
72 });
Alex Perrycb7da4b2019-08-28 19:35:56 -070073}
74
Austin Schuh39788ff2019-12-01 18:22:57 -080075inline bool RawFetcher::FetchNext() {
76 const auto result = DoFetchNext();
77 if (result.first) {
Brian Silvermanbf889922021-11-10 12:41:57 -080078 if (timing_.fetcher) {
79 timing_.fetcher->mutate_count(timing_.fetcher->count() + 1);
80 }
Austin Schuh39788ff2019-12-01 18:22:57 -080081 const monotonic_clock::time_point monotonic_time = result.second;
Brian Silverman79ec7fc2020-06-08 20:11:22 -050082 ftrace_.FormatMessage(
83 "%.*s: fetch next: now=%" PRId64 " event=%" PRId64 " queue=%" PRIu32,
84 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
85 static_cast<int64_t>(monotonic_time.time_since_epoch().count()),
86 static_cast<int64_t>(
87 context_.monotonic_event_time.time_since_epoch().count()),
88 context_.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -080089 const float latency =
90 std::chrono::duration_cast<std::chrono::duration<float>>(
Austin Schuhad154822019-12-27 15:45:13 -080091 monotonic_time - context_.monotonic_event_time)
Austin Schuh39788ff2019-12-01 18:22:57 -080092 .count();
93 timing_.latency.Add(latency);
94 return true;
95 }
Brian Silverman79ec7fc2020-06-08 20:11:22 -050096 ftrace_.FormatMessage(
97 "%.*s: fetch next: still event=%" PRId64 " queue=%" PRIu32,
98 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
99 static_cast<int64_t>(
100 context_.monotonic_event_time.time_since_epoch().count()),
101 context_.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -0800102 return false;
103}
104
Austin Schuh98ed26f2023-07-19 14:12:28 -0700105inline bool RawFetcher::FetchNextIf(std::function<bool(const Context &)> fn) {
106 DCHECK(fn);
107 const auto result = DoFetchNextIf(std::move(fn));
108 if (result.first) {
109 if (timing_.fetcher) {
110 timing_.fetcher->mutate_count(timing_.fetcher->count() + 1);
111 }
112 const monotonic_clock::time_point monotonic_time = result.second;
113 ftrace_.FormatMessage(
114 "%.*s: fetch next if: now=%" PRId64 " event=%" PRId64 " queue=%" PRIu32,
115 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
116 static_cast<int64_t>(monotonic_time.time_since_epoch().count()),
117 static_cast<int64_t>(
118 context_.monotonic_event_time.time_since_epoch().count()),
119 context_.queue_index);
120 const float latency =
121 std::chrono::duration_cast<std::chrono::duration<float>>(
122 monotonic_time - context_.monotonic_event_time)
123 .count();
124 timing_.latency.Add(latency);
125 return true;
126 }
127 ftrace_.FormatMessage(
128 "%.*s: fetch next: still event=%" PRId64 " queue=%" PRIu32,
129 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
130 static_cast<int64_t>(
131 context_.monotonic_event_time.time_since_epoch().count()),
132 context_.queue_index);
133 return false;
134}
135
Austin Schuh39788ff2019-12-01 18:22:57 -0800136inline bool RawFetcher::Fetch() {
137 const auto result = DoFetch();
138 if (result.first) {
Brian Silvermanbf889922021-11-10 12:41:57 -0800139 if (timing_.fetcher) {
140 timing_.fetcher->mutate_count(timing_.fetcher->count() + 1);
141 }
Austin Schuh39788ff2019-12-01 18:22:57 -0800142 const monotonic_clock::time_point monotonic_time = result.second;
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500143 ftrace_.FormatMessage(
144 "%.*s: fetch latest: now=%" PRId64 " event=%" PRId64 " queue=%" PRIu32,
145 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
146 static_cast<int64_t>(monotonic_time.time_since_epoch().count()),
147 static_cast<int64_t>(
148 context_.monotonic_event_time.time_since_epoch().count()),
149 context_.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -0800150 const float latency =
151 std::chrono::duration_cast<std::chrono::duration<float>>(
Austin Schuhad154822019-12-27 15:45:13 -0800152 monotonic_time - context_.monotonic_event_time)
Austin Schuh39788ff2019-12-01 18:22:57 -0800153 .count();
154 timing_.latency.Add(latency);
155 return true;
156 }
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500157 ftrace_.FormatMessage(
158 "%.*s: fetch latest: still event=%" PRId64 " queue=%" PRIu32,
159 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
160 static_cast<int64_t>(
161 context_.monotonic_event_time.time_since_epoch().count()),
162 context_.queue_index);
Austin Schuh39788ff2019-12-01 18:22:57 -0800163 return false;
164}
165
Austin Schuh98ed26f2023-07-19 14:12:28 -0700166inline bool RawFetcher::FetchIf(std::function<bool(const Context &)> fn) {
167 DCHECK(fn);
168
169 const auto result = DoFetchIf(std::move(fn));
170 if (result.first) {
171 if (timing_.fetcher) {
172 timing_.fetcher->mutate_count(timing_.fetcher->count() + 1);
173 }
174 const monotonic_clock::time_point monotonic_time = result.second;
175 ftrace_.FormatMessage(
176 "%.*s: fetch latest: now=%" PRId64 " event=%" PRId64 " queue=%" PRIu32,
177 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
178 static_cast<int64_t>(monotonic_time.time_since_epoch().count()),
179 static_cast<int64_t>(
180 context_.monotonic_event_time.time_since_epoch().count()),
181 context_.queue_index);
182 const float latency =
183 std::chrono::duration_cast<std::chrono::duration<float>>(
184 monotonic_time - context_.monotonic_event_time)
185 .count();
186 timing_.latency.Add(latency);
187 return true;
188 }
189 ftrace_.FormatMessage(
190 "%.*s: fetch latest: still event=%" PRId64 " queue=%" PRIu32,
191 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
192 static_cast<int64_t>(
193 context_.monotonic_event_time.time_since_epoch().count()),
194 context_.queue_index);
195 return false;
196}
197
milind1f1dca32021-07-03 13:50:07 -0700198inline RawSender::Error RawSender::Send(size_t size) {
Austin Schuhb5c6f972021-03-14 21:53:07 -0700199 return Send(size, monotonic_clock::min_time, realtime_clock::min_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700200 0xffffffffu, event_loop_->boot_uuid());
Austin Schuhb5c6f972021-03-14 21:53:07 -0700201}
202
milind1f1dca32021-07-03 13:50:07 -0700203inline RawSender::Error RawSender::Send(
Austin Schuhad154822019-12-27 15:45:13 -0800204 size_t size, aos::monotonic_clock::time_point monotonic_remote_time,
205 aos::realtime_clock::time_point realtime_remote_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700206 uint32_t remote_queue_index, const UUID &uuid) {
milind1f1dca32021-07-03 13:50:07 -0700207 const auto err = DoSend(size, monotonic_remote_time, realtime_remote_time,
208 remote_queue_index, uuid);
James Kuszmaul93abac12022-04-14 15:05:10 -0700209 RecordSendResult(err, size);
210 if (err == Error::kOk) {
211 ftrace_.FormatMessage(
212 "%.*s: sent internal: event=%" PRId64 " queue=%" PRIu32,
213 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
214 static_cast<int64_t>(monotonic_sent_time().time_since_epoch().count()),
215 sent_queue_index());
Austin Schuh39788ff2019-12-01 18:22:57 -0800216 }
milind1f1dca32021-07-03 13:50:07 -0700217 return err;
Austin Schuh39788ff2019-12-01 18:22:57 -0800218}
219
milind1f1dca32021-07-03 13:50:07 -0700220inline RawSender::Error RawSender::Send(const void *data, size_t size) {
Austin Schuhb5c6f972021-03-14 21:53:07 -0700221 return Send(data, size, monotonic_clock::min_time, realtime_clock::min_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700222 0xffffffffu, event_loop_->boot_uuid());
Austin Schuhb5c6f972021-03-14 21:53:07 -0700223}
224
milind1f1dca32021-07-03 13:50:07 -0700225inline RawSender::Error RawSender::Send(
Austin Schuhad154822019-12-27 15:45:13 -0800226 const void *data, size_t size,
227 aos::monotonic_clock::time_point monotonic_remote_time,
228 aos::realtime_clock::time_point realtime_remote_time,
Austin Schuh8902fa52021-03-14 22:39:24 -0700229 uint32_t remote_queue_index, const UUID &uuid) {
milind1f1dca32021-07-03 13:50:07 -0700230 const auto err = DoSend(data, size, monotonic_remote_time,
231 realtime_remote_time, remote_queue_index, uuid);
James Kuszmaul93abac12022-04-14 15:05:10 -0700232 RecordSendResult(err, size);
milind1f1dca32021-07-03 13:50:07 -0700233 if (err == RawSender::Error::kOk) {
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500234 ftrace_.FormatMessage(
235 "%.*s: sent external: event=%" PRId64 " queue=%" PRIu32,
236 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
237 static_cast<int64_t>(monotonic_sent_time().time_since_epoch().count()),
238 sent_queue_index());
Austin Schuh39788ff2019-12-01 18:22:57 -0800239 }
milind1f1dca32021-07-03 13:50:07 -0700240 return err;
Austin Schuh39788ff2019-12-01 18:22:57 -0800241}
242
milind1f1dca32021-07-03 13:50:07 -0700243inline RawSender::Error RawSender::Send(const SharedSpan data) {
Tyler Chatowb7c6eba2021-07-28 14:43:23 -0700244 return Send(std::move(data), monotonic_clock::min_time,
245 realtime_clock::min_time, 0xffffffffu, event_loop_->boot_uuid());
246}
247
milind1f1dca32021-07-03 13:50:07 -0700248inline RawSender::Error RawSender::Send(
Tyler Chatowb7c6eba2021-07-28 14:43:23 -0700249 const SharedSpan data,
250 aos::monotonic_clock::time_point monotonic_remote_time,
251 aos::realtime_clock::time_point realtime_remote_time,
252 uint32_t remote_queue_index, const UUID &uuid) {
253 const size_t size = data->size();
milind1f1dca32021-07-03 13:50:07 -0700254 const auto err = DoSend(std::move(data), monotonic_remote_time,
255 realtime_remote_time, remote_queue_index, uuid);
James Kuszmaul93abac12022-04-14 15:05:10 -0700256 RecordSendResult(err, size);
milind1f1dca32021-07-03 13:50:07 -0700257 if (err == Error::kOk) {
Tyler Chatowb7c6eba2021-07-28 14:43:23 -0700258 ftrace_.FormatMessage(
259 "%.*s: sent shared: event=%" PRId64 " queue=%" PRIu32,
260 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
261 static_cast<int64_t>(monotonic_sent_time().time_since_epoch().count()),
262 sent_queue_index());
Tyler Chatowb7c6eba2021-07-28 14:43:23 -0700263 }
milind1f1dca32021-07-03 13:50:07 -0700264 return err;
Tyler Chatowb7c6eba2021-07-28 14:43:23 -0700265}
266
Austin Schuh9b1d6282022-06-10 17:03:21 -0700267template <typename T>
Austin Schuhcde39fd2020-02-22 20:58:24 -0800268inline monotonic_clock::time_point TimerHandler::Call(
Austin Schuh9b1d6282022-06-10 17:03:21 -0700269 T get_time, monotonic_clock::time_point event_time) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800270 const monotonic_clock::time_point monotonic_start_time = get_time();
271
Austin Schuha9012be2021-07-21 15:19:11 -0700272 event_loop_->SetTimerContext(event_time);
Austin Schuh39788ff2019-12-01 18:22:57 -0800273
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500274 ftrace_.FormatMessage(
275 "timer: %.*s: start now=%" PRId64 " event=%" PRId64,
276 static_cast<int>(name_.size()), name_.data(),
277 static_cast<int64_t>(monotonic_start_time.time_since_epoch().count()),
278 static_cast<int64_t>(event_time.time_since_epoch().count()));
Brian Silvermanbf889922021-11-10 12:41:57 -0800279 if (timing_.timer) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800280 const float start_latency =
281 std::chrono::duration_cast<std::chrono::duration<float>>(
282 monotonic_start_time - event_time)
283 .count();
284 timing_.wakeup_latency.Add(start_latency);
Brian Silvermanbf889922021-11-10 12:41:57 -0800285 timing_.timer->mutate_count(timing_.timer->count() + 1);
Austin Schuh39788ff2019-12-01 18:22:57 -0800286 }
Austin Schuh39788ff2019-12-01 18:22:57 -0800287 fn_();
288
289 const monotonic_clock::time_point monotonic_end_time = get_time();
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500290 ftrace_.FormatMessage(
291 "timer: %.*s: end now=%" PRId64, static_cast<int>(name_.size()),
292 name_.data(),
293 static_cast<int64_t>(monotonic_end_time.time_since_epoch().count()));
Austin Schuh39788ff2019-12-01 18:22:57 -0800294
295 const float handler_latency =
296 std::chrono::duration_cast<std::chrono::duration<float>>(
297 monotonic_end_time - monotonic_start_time)
298 .count();
299 timing_.handler_time.Add(handler_latency);
Austin Schuhcde39fd2020-02-22 20:58:24 -0800300 return monotonic_start_time;
Austin Schuh39788ff2019-12-01 18:22:57 -0800301}
302
303inline void PhasedLoopHandler::Call(
James Kuszmaul20dcc7c2023-01-20 11:06:31 -0800304 std::function<monotonic_clock::time_point()> get_time) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800305 // Read time directly to save a vtable indirection...
306 const monotonic_clock::time_point monotonic_start_time = get_time();
307
308 // Update the context to hold the desired wakeup time.
Austin Schuha9012be2021-07-21 15:19:11 -0700309 event_loop_->SetTimerContext(phased_loop_.sleep_time());
Austin Schuh39788ff2019-12-01 18:22:57 -0800310
Milind Upadhyay42589bb2021-05-19 20:05:16 -0700311 // Compute how many cycles elapsed
312 cycles_elapsed_ += phased_loop_.Iterate(monotonic_start_time);
Austin Schuh39788ff2019-12-01 18:22:57 -0800313
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500314 ftrace_.FormatMessage(
315 "phased: %.*s: start now=%" PRId64 " event=%" PRId64 " cycles=%d",
316 static_cast<int>(name_.size()), name_.data(),
317 static_cast<int64_t>(monotonic_start_time.time_since_epoch().count()),
318 static_cast<int64_t>(
319 phased_loop_.sleep_time().time_since_epoch().count()),
320 cycles_elapsed_);
Brian Silvermanbf889922021-11-10 12:41:57 -0800321 if (timing_.timer) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800322 const float start_latency =
323 std::chrono::duration_cast<std::chrono::duration<float>>(
Austin Schuhad154822019-12-27 15:45:13 -0800324 monotonic_start_time - event_loop_->context_.monotonic_event_time)
Austin Schuh39788ff2019-12-01 18:22:57 -0800325 .count();
326 timing_.wakeup_latency.Add(start_latency);
Brian Silvermanbf889922021-11-10 12:41:57 -0800327 timing_.timer->mutate_count(timing_.timer->count() + 1);
Austin Schuh39788ff2019-12-01 18:22:57 -0800328 }
Austin Schuh39788ff2019-12-01 18:22:57 -0800329
330 // Call the function with the elapsed cycles.
331 fn_(cycles_elapsed_);
332 cycles_elapsed_ = 0;
333
Milind Upadhyay42589bb2021-05-19 20:05:16 -0700334 // Schedule the next wakeup.
James Kuszmaul20dcc7c2023-01-20 11:06:31 -0800335 Schedule(phased_loop_.sleep_time());
Milind Upadhyay42589bb2021-05-19 20:05:16 -0700336
Austin Schuh39788ff2019-12-01 18:22:57 -0800337 const monotonic_clock::time_point monotonic_end_time = get_time();
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500338 ftrace_.FormatMessage(
339 "phased: %.*s: end now=%" PRId64, static_cast<int>(name_.size()),
340 name_.data(),
341 static_cast<int64_t>(monotonic_end_time.time_since_epoch().count()));
Austin Schuh39788ff2019-12-01 18:22:57 -0800342
343 const float handler_latency =
344 std::chrono::duration_cast<std::chrono::duration<float>>(
345 monotonic_end_time - monotonic_start_time)
346 .count();
347 timing_.handler_time.Add(handler_latency);
348
Brian Silvermanaf9a4d82020-10-06 15:10:58 -0700349 // If the handler took too long so we blew by the previous deadline, we
Austin Schuh91ba6392020-10-03 13:27:47 -0700350 // want to just try for the next deadline. Reschedule.
Austin Schuh39788ff2019-12-01 18:22:57 -0800351 if (monotonic_end_time > phased_loop_.sleep_time()) {
James Kuszmaul20dcc7c2023-01-20 11:06:31 -0800352 Reschedule(monotonic_end_time);
Austin Schuh39788ff2019-12-01 18:22:57 -0800353 }
354}
355
356// Class to automate the timing report generation for watchers.
357class WatcherState {
358 public:
359 WatcherState(
360 EventLoop *event_loop, const Channel *channel,
361 std::function<void(const Context &context, const void *message)> fn)
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500362 : channel_index_(event_loop->ChannelIndex(channel)),
363 ftrace_prefix_(configuration::StrippedChannelToString(channel)),
364 fn_(std::move(fn)) {}
Austin Schuh39788ff2019-12-01 18:22:57 -0800365
366 virtual ~WatcherState() {}
367
368 // Calls the callback, measuring time with get_time, with the provided
369 // context.
370 void DoCallCallback(std::function<monotonic_clock::time_point()> get_time,
Austin Schuhc5dc98f2021-06-16 14:52:46 -0700371 Context context) noexcept {
Brian Silverman6b8a3c32020-03-06 11:26:14 -0800372 if (context.data) {
373 CheckChannelDataAlignment(context.data, context.size);
374 }
Austin Schuh39788ff2019-12-01 18:22:57 -0800375 const monotonic_clock::time_point monotonic_start_time = get_time();
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500376 ftrace_.FormatMessage(
377 "%.*s: watcher start: now=%" PRId64 " event=%" PRId64 " queue=%" PRIu32,
378 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
379 static_cast<int64_t>(monotonic_start_time.time_since_epoch().count()),
380 static_cast<int64_t>(
381 context.monotonic_event_time.time_since_epoch().count()),
382 context.queue_index);
Brian Silvermanbf889922021-11-10 12:41:57 -0800383 if (watcher_) {
Austin Schuh39788ff2019-12-01 18:22:57 -0800384 const float start_latency =
385 std::chrono::duration_cast<std::chrono::duration<float>>(
Austin Schuhad154822019-12-27 15:45:13 -0800386 monotonic_start_time - context.monotonic_event_time)
Austin Schuh39788ff2019-12-01 18:22:57 -0800387 .count();
388 wakeup_latency_.Add(start_latency);
Brian Silvermanbf889922021-11-10 12:41:57 -0800389 watcher_->mutate_count(watcher_->count() + 1);
Austin Schuh39788ff2019-12-01 18:22:57 -0800390 }
Austin Schuh39788ff2019-12-01 18:22:57 -0800391 fn_(context, context.data);
392
393 const monotonic_clock::time_point monotonic_end_time = get_time();
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500394 ftrace_.FormatMessage(
395 "%.*s: watcher end: now=%" PRId64,
396 static_cast<int>(ftrace_prefix_.size()), ftrace_prefix_.data(),
397 static_cast<int64_t>(monotonic_end_time.time_since_epoch().count()));
Austin Schuh39788ff2019-12-01 18:22:57 -0800398
399 const float handler_latency =
400 std::chrono::duration_cast<std::chrono::duration<float>>(
401 monotonic_end_time - monotonic_start_time)
402 .count();
403 handler_time_.Add(handler_latency);
404 }
405
406 int channel_index() const { return channel_index_; }
407
408 void set_timing_report(timing::Watcher *watcher);
409 void ResetReport();
410
Philipp Schrader81fa3fb2023-09-17 18:58:35 -0700411 virtual void Construct() = 0;
412 virtual void Startup() = 0;
Austin Schuh39788ff2019-12-01 18:22:57 -0800413
414 protected:
415 const int channel_index_;
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500416 const std::string ftrace_prefix_;
Austin Schuh39788ff2019-12-01 18:22:57 -0800417
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500418 const std::function<void(const Context &context, const void *message)> fn_;
Austin Schuh39788ff2019-12-01 18:22:57 -0800419
420 internal::TimingStatistic wakeup_latency_;
421 internal::TimingStatistic handler_time_;
422 timing::Watcher *watcher_ = nullptr;
Brian Silverman79ec7fc2020-06-08 20:11:22 -0500423
424 Ftrace ftrace_;
Austin Schuh39788ff2019-12-01 18:22:57 -0800425};
426
Austin Schuha28cbc32019-12-27 16:28:04 -0800427template <typename T>
milind1f1dca32021-07-03 13:50:07 -0700428RawSender::Error Sender<T>::Send(
429 const NonSizePrefixedFlatbuffer<T> &flatbuffer) {
James Kuszmaulef90fb52024-01-07 21:10:37 -0800430 CHECK(valid()) << ": Sender must be initialized before sending.";
Austin Schuhadd6eb32020-11-09 21:24:26 -0800431 return sender_->Send(flatbuffer.span().data(), flatbuffer.span().size());
Austin Schuha28cbc32019-12-27 16:28:04 -0800432}
433
Brian Silverman341b57e2020-06-23 16:23:18 -0700434template <typename T>
milind1f1dca32021-07-03 13:50:07 -0700435RawSender::Error Sender<T>::SendDetached(FlatbufferDetachedBuffer<T> detached) {
Austin Schuhadd6eb32020-11-09 21:24:26 -0800436 CHECK_EQ(static_cast<void *>(detached.span().data() + detached.span().size() -
437 sender_->size()),
438 sender_->data())
Brian Silverman341b57e2020-06-23 16:23:18 -0700439 << ": May only send the buffer detached from this Sender";
Austin Schuhadd6eb32020-11-09 21:24:26 -0800440 return sender_->Send(detached.span().size());
Brian Silverman341b57e2020-06-23 16:23:18 -0700441}
442
Alex Perrycb7da4b2019-08-28 19:35:56 -0700443} // namespace aos
444
445#endif // AOS_EVENTS_EVENT_LOOP_TMPL_H