tin  1.5.9
actor.h
Go to the documentation of this file.
1 // Copyright (c) 2026 Tinverse LLC. All rights reserved.
2 // SPDX-License-Identifier: LicenseRef-Tinverse-Commercial
3 
14 
15 #pragma once
16 
17 #include <cstddef>
18 #include <tuple>
19 #include <type_traits>
20 #include <utility>
21 
22 #include "tsm/runtime/concepts.h"
23 #include "tsm/runtime/resources.h"
24 
25 namespace tsm::runtime {
26 
27 template<typename Actor>
28 struct actor_resources;
29 
36 // clang-format disagrees across the versions used by local toolchains and CI
37 // for C++20 requires-expressions. Keep this declaration block stable.
38 // clang-format off
39 template<typename Actor>
40 concept actor_like = requires(Actor actor) {
41  { actor.step() } -> std::convertible_to<bool>;
42  { actor.drain() } -> std::convertible_to<std::size_t>;
43  { actor.empty() } -> std::convertible_to<bool>;
44  { actor.pending_events() } -> std::convertible_to<std::size_t>;
45 };
46 
52 template<typename Actor, typename Event>
53 concept actor_sink = requires(Actor actor, Event event) {
54  { actor.send_event(event) } -> std::convertible_to<bool>;
55 };
56 
61 template<typename Actor, typename Event>
62 concept actor_source = requires(Actor actor, Event& event) {
63  { actor.try_receive(event) } -> std::convertible_to<bool>;
64 };
65 
66 template<typename Event, typename Sink>
72 struct input_port
73 {
75  using event_type = Event;
76 
78  using sink_type = Sink;
79 
84  explicit constexpr input_port(Sink& sink)
85  : sink_(&sink)
86  {
87  }
88 
93  [[nodiscard]] bool try_send(Event const& event) const
94  requires actor_sink<Sink, Event>
95  {
96  return sink_->send_event(event);
97  }
98 
104  [[nodiscard]] bool try_send(Event&& event) const
105  requires actor_sink<Sink, Event>
106  {
107  return sink_->send_event(std::move(event));
108  }
109 
111  [[nodiscard]] bool send_event(Event const& event) const
112  requires actor_sink<Sink, Event>
113  {
114  return try_send(event);
115  }
116 
118  [[nodiscard]] bool send_event(Event&& event) const
119  requires actor_sink<Sink, Event>
120  {
121  return try_send(std::move(event));
122  }
123 
124  private:
125  Sink* sink_{};
126 };
127 
128 template<typename Event, typename Source>
134 {
136  using event_type = Event;
137 
139  using source_type = Source;
140 
145  explicit constexpr output_port(Source& source)
146  : source_(&source)
147  {
148  }
149 
154  [[nodiscard]] bool try_receive(Event& event) const
155  requires actor_source<Source, Event>
156  {
157  return source_->try_receive(event);
158  }
159 
160  private:
161  Source* source_{};
162 };
163 
167 template<typename Event, typename Sink>
168 [[nodiscard]] constexpr input_port<Event, Sink>
169 make_input_port(Sink& sink)
170 {
171  return input_port<Event, Sink>{ sink };
172 }
173 
177 template<typename Event, typename Source>
178 [[nodiscard]] constexpr output_port<Event, Source>
179 make_output_port(Source& source)
180 {
181  return output_port<Event, Source>{ source };
182 }
183 
188 template<typename Source, typename Sink>
190  typename Source::event_type;
191  typename Sink::event_type;
192  requires std::same_as<typename Source::event_type,
193  typename Sink::event_type>;
194 } && requires(Source source, Sink sink, typename Source::event_type event) {
195  { source.try_receive(event) } -> std::convertible_to<bool>;
196  { sink.try_send(event) } -> std::convertible_to<bool>;
197 };
198 
204 template<typename Source, typename Sink>
206 {
208  using event_type = typename Source::event_type;
209 
213  constexpr actor_link(Source& source, Sink& sink)
214  : source_(&source)
215  , sink_(&sink)
216  {
217  }
218 
224  [[nodiscard]] bool step()
225  {
226  if (has_pending_) {
227  if (!sink_->try_send(pending_)) {
228  return false;
229  }
230  has_pending_ = false;
231  return true;
232  }
233 
234  if (!source_->try_receive(pending_)) {
235  return false;
236  }
237  has_pending_ = true;
238  if (!sink_->try_send(pending_)) {
239  return false;
240  }
241  has_pending_ = false;
242  return true;
243  }
244 
246  [[nodiscard]] bool pending() const noexcept
247  {
248  return has_pending_;
249  }
250 
251  private:
252  Source* source_{};
253  Sink* sink_{};
254  event_type pending_{};
255  bool has_pending_{};
256 };
257 
258 template<typename Source, typename Sink>
260 
265 template<typename... Links>
266 [[nodiscard]] bool
267 link_all(Links&... links)
268 {
269  bool progressed{};
270  ((progressed = links.step() || progressed), ...);
271  return progressed;
272 }
273 
278 template<actor_like... Actors>
280 {
284  explicit constexpr actor_group(Actors&... actors)
285  : actors_(&actors...)
286  {
287  }
288 
292  [[nodiscard]] bool step()
293  {
294  bool progressed{};
295  std::apply(
296  [&progressed](auto*... actor) {
297  ((progressed = actor->step() || progressed), ...);
298  },
299  actors_);
300  return progressed;
301  }
302 
307  std::size_t drain()
308  {
309  std::size_t rounds{};
310  while (step()) {
311  ++rounds;
312  }
313  return rounds;
314  }
315 
317  [[nodiscard]] bool empty() const
318  {
319  bool all_empty{ true };
320  std::apply(
321  [&all_empty](auto const*... actor) {
322  ((all_empty = all_empty && actor->empty()), ...);
323  },
324  actors_);
325  return all_empty;
326  }
327 
329  [[nodiscard]] std::size_t pending_events() const
330  {
331  std::size_t pending{};
332  std::apply(
333  [&pending](auto const*... actor) {
334  ((pending += actor->pending_events()), ...);
335  },
336  actors_);
337  return pending;
338  }
339 
340  private:
341  std::tuple<Actors*...> actors_;
342 };
343 
344 template<typename... Actors>
345 actor_group(Actors&...) -> actor_group<Actors...>;
346 
347 namespace detail {
348 
349 template<typename Actor, typename = void>
350 struct has_runtime_resource_shape : std::false_type
351 {};
352 
353 template<typename Actor>
354 struct has_runtime_resource_shape<
355  Actor,
356  std::void_t<typename Actor::events, typename Actor::policy>> : std::true_type
357 {};
358 
359 template<typename Actor, typename = void>
360 struct has_custom_resource_snapshot : std::false_type
361 {};
362 
363 template<typename Actor>
364 struct has_custom_resource_snapshot<
365  Actor,
366  std::void_t<decltype(Actor::resource_snapshot())>> : std::true_type
367 {};
368 // clang-format on
369 
370 [[nodiscard]] consteval resource_snapshot
372 {
373  return resource_snapshot{
375  : rhs.max_event_bytes,
377  ? lhs.max_event_alignment
378  : rhs.max_event_alignment,
379  lhs.queue_slots + rhs.queue_slots,
381  lhs.task_count + rhs.task_count,
386  lhs.uses_heap || rhs.uses_heap
387  };
388 }
389 
390 } // namespace detail
391 
392 template<typename Actor>
399 {
401  static consteval resource_snapshot snapshot()
402  {
403  if constexpr (detail::has_runtime_resource_shape<Actor>::value) {
405  } else if constexpr (detail::has_custom_resource_snapshot<
406  Actor>::value) {
407  return Actor::resource_snapshot();
408  } else {
409  return resource_snapshot{};
410  }
411  }
412 };
413 
414 template<typename... Actors>
417 {
419  static consteval resource_snapshot snapshot()
420  {
421  resource_snapshot total{};
424  ...);
425  return total;
426  }
427 
429  static consteval bool fits_within(resource_budget const& budget)
430  {
431  return fits(snapshot(), budget);
432  }
433 };
434 
435 } // namespace tsm::runtime
Concepts for runtime queues and dispatch policies.
requires(!has_transition_type_c< T > &&has_transition_member_c< T >) struct transitions_of< T >
Definition: transition.h:479
consteval resource_snapshot add_resource_snapshots(resource_snapshot lhs, resource_snapshot rhs)
Definition: actor.h:371
Definition: freertos.h:26
actor_link(Source &, Sink &) -> actor_link< Source, Sink >
concept actor_source
Definition: actor.h:62
constexpr input_port< Event, Sink > make_input_port(Sink &sink)
Definition: actor.h:169
actor_group(Actors &...) -> actor_group< Actors... >
concept actor_sink
Definition: actor.h:53
bool link_all(Links &... links)
Definition: actor.h:267
concept actor_like
Definition: actor.h:40
constexpr output_port< Event, Source > make_output_port(Source &source)
Definition: actor.h:179
concept compatible_link
Definition: actor.h:189
consteval bool fits(resource_snapshot const &snapshot, resource_budget const &budget)
Definition: resources.h:51
runtime::resource_snapshot resource_snapshot
Definition: runtime.h:131
Static resource accounting for runtimes and task executors.
Aggregate resource summaries for several actor types.
Definition: actor.h:417
static consteval bool fits_within(resource_budget const &budget)
Return whether the aggregate actor resources fit within budget.
Definition: actor.h:429
static consteval resource_snapshot snapshot()
Return the combined resource snapshot for all actor types.
Definition: actor.h:419
Definition: actor.h:280
std::size_t drain()
Definition: actor.h:307
bool step()
Definition: actor.h:292
bool empty() const
Report whether every actor currently has no pending work.
Definition: actor.h:317
constexpr actor_group(Actors &... actors)
Definition: actor.h:284
std::size_t pending_events() const
Return the sum of each actor's pending-event count.
Definition: actor.h:329
Definition: actor.h:399
static consteval resource_snapshot snapshot()
Return the compile-time resource snapshot for Actor.
Definition: actor.h:401
Definition: actor.h:73
Sink sink_type
Actor or adapter type referenced by this port.
Definition: actor.h:78
bool try_send(Event const &event) const requires actor_sink< Sink
bool send_event(Event &&event) const requires actor_sink< Sink
Move-sending alias for try_send(std::move(event)).
constexpr input_port(Sink &sink)
Definition: actor.h:84
bool Event
Definition: actor.h:95
Event event_type
Event type accepted by this port.
Definition: actor.h:75
bool send_event(Event const &event) const requires actor_sink< Sink
Alias for try_send(event) that satisfies event-sink shaped code.
bool try_send(Event &&event) const requires actor_sink< Sink
Definition: actor.h:134
Source source_type
Actor or adapter type referenced by this port.
Definition: actor.h:139
constexpr output_port(Source &source)
Definition: actor.h:145
bool Event
Definition: actor.h:156
Event event_type
Event type produced by this port.
Definition: actor.h:136
bool try_receive(Event &event) const requires actor_source< Source
Definition: resources.h:37
Definition: resources.h:23
std::size_t max_event_bytes
Definition: resources.h:24
std::size_t delayed_event_timer_slots
Definition: resources.h:27
std::size_t task_timer_slots
Definition: resources.h:32
std::size_t task_arena_bytes
Definition: resources.h:31
std::size_t max_event_alignment
Definition: resources.h:25
bool uses_heap
Definition: resources.h:33
std::size_t queue_slots
Definition: resources.h:26
std::size_t task_group_entry_count
Definition: resources.h:30
std::size_t task_count
Definition: resources.h:28
std::size_t task_group_count
Definition: resources.h:29
static consteval resource_snapshot snapshot()
Definition: resources.h:118