24 #include <type_traits>
40 template<
typename Definition>
41 struct default_machine_policy
56 template<
typename Overflow>
57 struct overflow_strategy;
62 template<
typename Queue,
typename Event>
63 [[nodiscard]]
static bool push(Queue& queue, Event&& event)
65 return queue.try_push(std::forward<Event>(event));
72 template<
typename Queue,
typename Event>
73 [[nodiscard]]
static bool push(Queue& queue, Event&& event)
75 if (queue.try_push(std::forward<Event>(event))) {
78 typename Queue::value_type discarded{};
79 if (!queue.try_pop(discarded)) {
82 return queue.try_push(std::forward<Event>(event));
89 template<
typename Queue,
typename Event>
90 [[nodiscard]]
static bool push(Queue& queue, Event&& event)
92 if (queue.try_push(std::forward<Event>(event))) {
95 return queue.try_overwrite_latest(std::forward<Event>(event));
99 template<
typename Definition,
103 typename Topology =
typename Policy::topology>
114 template<
typename Definition,
118 class runtime_impl<Definition, Policy, MachinePolicy, topology::
direct_dispatch>
121 using definition = Definition;
123 using machine_type =
typename MachinePolicy<Definition>::type;
124 using context_type =
typename machine_type::context_type;
127 [[nodiscard]] machine_type& machine() noexcept
131 [[nodiscard]] machine_type
const& machine() const noexcept
136 [[nodiscard]] context_type& context() noexcept
138 return machine_.context();
140 [[nodiscard]] context_type
const& context() const noexcept
142 return machine_.context();
145 template<
typename Event>
152 last_event_handled_ = machine_.handle(std::forward<Event>(event));
153 return last_event_handled_;
156 [[nodiscard]]
bool step()
158 last_event_handled_ =
false;
167 [[nodiscard]]
bool empty()
const
171 [[nodiscard]] std::size_t pending_events()
const
175 [[nodiscard]]
bool last_event_handled()
const
177 return last_event_handled_;
181 machine_type machine_{};
182 bool last_event_handled_{};
194 template<
typename Definition,
198 class runtime_impl<Definition, Policy, MachinePolicy, topology::
composite_queue>
201 using definition = Definition;
203 using machine_type =
typename MachinePolicy<Definition>::type;
204 using context_type =
typename machine_type::context_type;
206 using queued_event = tsm::detail::erased_event<machine_type, events>;
207 using queue_type =
typename Policy::storage::template queue<queued_event>;
209 static_assert(queue_storage<queue_type, queued_event>,
210 "tsm: composite queue storage must satisfy queue_storage");
212 [[nodiscard]] machine_type& machine() noexcept
216 [[nodiscard]] machine_type
const& machine() const noexcept
221 [[nodiscard]] context_type& context() noexcept
223 return machine_.context();
225 [[nodiscard]] context_type
const& context() const noexcept
227 return machine_.context();
230 template<
typename Event>
238 queued_event queued(std::forward<Event>(event));
239 return overflow_strategy<typename Policy::overflow>::push(
240 event_queue_, std::move(queued));
243 [[nodiscard]]
bool step()
248 queued_event
event{};
249 if (!event_queue_.try_pop(event)) {
250 last_event_handled_ =
false;
253 last_event_handled_ =
event.dispatch(machine_);
261 std::size_t dispatched{};
262 while (!event_queue_.empty()) {
263 static_cast<void>(step());
269 [[nodiscard]]
bool empty()
const
271 return event_queue_.empty();
273 [[nodiscard]] std::size_t pending_events()
const
275 return event_queue_.size();
277 [[nodiscard]]
bool last_event_handled()
const
279 return last_event_handled_;
283 machine_type machine_{};
284 queue_type event_queue_{};
285 bool last_event_handled_{};
293 template<
typename Machine,
typename RegionDefinition,
typename Storage>
297 using region_definition = RegionDefinition;
298 using region_hsm =
typename Machine::template region_hsm<RegionDefinition>;
300 using queued_event = tsm::detail::erased_event<region_hsm, events>;
301 using queue_type =
typename Storage::template queue<queued_event>;
303 static_assert(queue_storage<queue_type, queued_event>,
304 "tsm: region queue storage must satisfy queue_storage");
306 template<
typename Event>
307 static consteval
bool accepts()
309 return tsm::detail::contains_type<Event>(
313 template<
typename Event,
typename Overflow>
314 [[nodiscard]]
bool send(Event&& event)
316 queued_event queued(std::forward<Event>(event));
317 return overflow_strategy<Overflow>::push(queue_, std::move(queued));
320 [[nodiscard]]
bool step(Machine& machine,
bool& handled)
322 queued_event
event{};
323 if (!queue_.try_pop(event)) {
326 handled =
event.dispatch(machine.template region<RegionDefinition>());
330 [[nodiscard]]
bool empty()
const
332 return queue_.empty();
334 [[nodiscard]] std::size_t pending_events()
const
336 return queue_.size();
354 template<
typename... RegionDefinitions,
358 class runtime_impl<
tsm::detail::OrthogonalExecutionPolicy<RegionDefinitions...>,
365 tsm::detail::OrthogonalExecutionPolicy<RegionDefinitions...>;
367 using machine_type = definition;
368 using regions =
typename machine_type::regions;
369 using queues = std::tuple<region_queue<machine_type,
371 typename Policy::storage>...>;
373 [[nodiscard]] machine_type& machine() noexcept
377 [[nodiscard]] machine_type
const& machine() const noexcept
382 template<
typename RegionDefinition,
typename Event>
387 using event_type = std::decay_t<Event>;
388 using queue_holder = region_queue<machine_type,
390 typename Policy::storage>;
391 static_assert(queue_holder::template accepts<event_type>(),
392 "tsm: region queue cannot accept this event type");
393 return std::get<queue_holder>(queues_)
394 .template send<Event, typename Policy::overflow>(
395 std::forward<Event>(event));
398 template<
typename Event>
399 [[nodiscard]]
bool broadcast_event(Event
const& event)
405 bool matched =
false;
406 broadcast_event_impl<std::decay_t<Event>, 0U>(event,
accepted, matched);
410 [[nodiscard]]
bool step()
415 last_event_handled_ =
false;
416 return step_region<0U>();
421 std::size_t dispatched{};
423 static_cast<void>(step());
429 [[nodiscard]]
bool empty()
const
431 return empty_region<0U>();
434 [[nodiscard]] std::size_t pending_events()
const
436 return pending_region<0U>();
439 [[nodiscard]]
bool last_event_handled()
const
441 return last_event_handled_;
445 template<std::
size_t Index>
446 [[nodiscard]]
bool step_region()
448 if constexpr (Index <
sizeof...(RegionDefinitions)) {
450 using queue_holder = region_queue<machine_type,
452 typename Policy::storage>;
453 if (std::get<queue_holder>(queues_).step(machine_,
454 last_event_handled_)) {
457 return step_region<Index + 1U>();
463 template<std::
size_t Index>
464 [[nodiscard]]
bool empty_region()
const
466 if constexpr (Index <
sizeof...(RegionDefinitions)) {
468 using queue_holder = region_queue<machine_type,
470 typename Policy::storage>;
471 return std::get<queue_holder>(queues_).empty() &&
472 empty_region<Index + 1U>();
478 template<std::
size_t Index>
479 [[nodiscard]] std::size_t pending_region()
const
481 if constexpr (Index <
sizeof...(RegionDefinitions)) {
483 using queue_holder = region_queue<machine_type,
485 typename Policy::storage>;
486 return std::get<queue_holder>(queues_).pending_events() +
487 pending_region<Index + 1U>();
493 template<
typename Event, std::
size_t Index>
494 void broadcast_event_impl(Event
const& event,
bool& accepted,
bool& matched)
496 if constexpr (Index <
sizeof...(RegionDefinitions)) {
498 using queue_holder = region_queue<machine_type,
500 typename Policy::storage>;
501 if constexpr (queue_holder::template accepts<Event>()) {
504 std::get<queue_holder>(queues_)
505 .template send<Event const&, typename Policy::overflow>(
509 broadcast_event_impl<Event, Index + 1U>(event, accepted, matched);
513 machine_type machine_{};
515 bool last_event_handled_{};
527 template<
typename Definition,
529 template<
typename>
class MachinePolicy =
530 detail::default_machine_policy>
531 using Runtime = detail::runtime_impl<Definition, Policy, MachinePolicy>;
533 template<
typename Definition,
535 template<
typename>
class MachinePolicy =
536 detail::default_machine_policy>
539 template<
typename Definition,
540 template<
typename>
class MachinePolicy =
541 detail::default_machine_policy>
548 template<
typename Definition,
549 std::size_t Capacity,
551 template<
typename>
class MachinePolicy =
552 detail::default_machine_policy>
560 template<
typename Definition,
561 std::size_t Capacity,
563 template<
typename>
class MachinePolicy =
564 detail::default_machine_policy>
unique_tuple_t< typename get_events_from_hsm< HsmType >::type > get_events_t
Definition: tsm.h:2077
typename make_hsm< T >::type make_hsm_t
Definition: tsm.h:1489
requires(!has_transition_type_c< T > &&has_transition_member_c< T >) struct transitions_of< T >
Definition: transition.h:479
typename as_type_list< T >::type as_type_list_t
Definition: type_list.h:175
typename type_at< Index, List >::type type_at_t
Definition: type_list.h:100
consteval bool contains_type(type_list< Ts... >)
Definition: type_list.h:124
Definition: concepts.h:40
::tsm::overflow::reject_newest reject_newest
Definition: concepts.h:87
::tsm::overflow::drop_oldest drop_oldest
Definition: concepts.h:88
::tsm::overflow::overwrite_latest overwrite_latest
Definition: concepts.h:89
::tsm::dispatch_model::per_region_queued per_region_queue
Definition: concepts.h:81
::tsm::dispatch_model::queued composite_queue
Definition: concepts.h:80
::tsm::dispatch_model::direct direct_dispatch
Definition: concepts.h:79
Definition: freertos.h:26
detail::runtime_impl< Definition, Policy, MachinePolicy > Runtime
Definition: runtime.h:531
Runtime< Definition, ::tsm::runtime_policy< ::tsm::dispatch_model::queued, ::tsm::queue_policy<::tsm::target_storage< Capacity >, Overflow > >, MachinePolicy > queued_runtime
Definition: runtime.h:558
Runtime< Definition, ::tsm::runtime_policy< ::tsm::dispatch_model::per_region_queued, ::tsm::queue_policy<::tsm::target_storage< Capacity >, Overflow > >, MachinePolicy > per_region_runtime
Definition: runtime.h:570
Runtime< Definition, Policy, MachinePolicy > runtime_for
Definition: runtime.h:537
::tsm::runtime_policy< Topology, Storage, Scheduler, Overflow, Transport > policy
Definition: policy.h:119
Runtime< Definition, ::tsm::runtime_policy<::tsm::dispatch_model::direct, ::tsm::queue_policy<::tsm::static_storage< 2 > >>, MachinePolicy > direct_runtime
Definition: runtime.h:546
Definition: bare_metal.h:20
auto send_event(Runtime &runtime, Event &&event)
Definition: coroutine.h:972
auto send(Runtime &runtime, Args &&... args)
Definition: coroutine.h:980
Runtime policy tags for dispatch and bounded queue admission.
Fixed-capacity ring queue storage for runtime events.
Local runtime transport boundary for typed events.