83 static constexpr const auto&
conf = Conf;
85#ifndef MAKI_DETAIL_DOXYGEN
86 using option_set_type = std::decay_t<
decltype(impl_of(
conf))>;
89#ifdef MAKI_DETAIL_DOXYGEN
95 using context_type =
typename option_set_type::context_type;
100 detail::is_machine_conf_v<std::decay_t<
decltype(
conf)>>,
101 "Given `Conf` must be an instance of `maki::machine_conf`"
116 template<
class... ContextArgs>
118 ctx_holder_(*this, std::forward<ContextArgs>(ctx_args)...),
121 if constexpr(impl_of(
conf).auto_start)
123 MAKI_DETAIL_MAYBE_CATCH(start_now())
138 return ctx_holder_.get();
146 return ctx_holder_.get();
156 return !impl_.completed();
170 template<
class Event = events::start>
173 MAKI_DETAIL_MAYBE_CATCH(start_no_catch(event))
184 template<
class Event = events::stop>
185 void stop(
const Event& event = {})
187 MAKI_DETAIL_MAYBE_CATCH(stop_no_catch(event))
239 template<
class Event>
249 template<
class Event>
252 execute_operation<detail::machine_operation::process_event>(event);
274 template<
class Event>
277 MAKI_DETAIL_MAYBE_CATCH(process_event_now_no_catch(event))
291 template<
class Event>
294 auto processed =
false;
295 impl_.template call_internal_action<true>(*
this,
context(), event, processed);
309 template<
class Event>
312 MAKI_DETAIL_MAYBE_CATCH(push_event_no_catch(event))
328 template<const auto& StateMold>
329 [[nodiscard]]
const auto&
state()
const
339 template<const auto& StateMold>
340 [[nodiscard]]
bool is()
const
346 class executing_operation_guard
349 executing_operation_guard(
machine& self):
352 self_.executing_operation_ =
true;
355 executing_operation_guard(
const executing_operation_guard&) =
delete;
356 executing_operation_guard(executing_operation_guard&&) =
delete;
357 executing_operation_guard& operator=(
const executing_operation_guard&) =
delete;
358 executing_operation_guard& operator=(executing_operation_guard&&) =
delete;
360 ~executing_operation_guard()
362 self_.executing_operation_ =
false;
369 struct real_operation_queue_holder
371 template<
bool = true>
372 using type = detail::function_queue
375 impl_of(
conf).small_event_max_size,
376 impl_of(
conf).small_event_max_align
381 template<
bool = true>
384 using operation_queue_type =
typename std::conditional_t
386 impl_of(
conf).run_to_completion,
387 real_operation_queue_holder,
393 execute_operation_now<detail::machine_operation::start>(
events::start{});
396 template<
class Event>
397 void start_no_catch(
const Event& event)
401 execute_operation<detail::machine_operation::start>(event);
405 template<
class Event>
406 void stop_no_catch(
const Event& event)
410 execute_operation<detail::machine_operation::stop>(event);
414 template<
class Event>
415 void process_event_now_no_catch(
const Event& event)
419 impl_of(
conf).process_event_now_enabled,
420 "`maki::machine_conf::process_event_now_enabled()` hasn't been set to `true`"
422 execute_operation_now<detail::machine_operation::process_event>(event);
425 template<detail::machine_operation Operation,
class Event>
426 void execute_operation(
const Event& event)
428 if constexpr(impl_of(
conf).run_to_completion)
430 if(!executing_operation_)
432 execute_operation_now<Operation>(event);
437 push_event_impl<Operation>(event);
442 execute_one_operation<Operation>(event);
446 template<detail::machine_operation Operation,
class Event>
447 void execute_operation_now(
const Event& event)
449 if constexpr(impl_of(
conf).run_to_completion)
451 auto grd = executing_operation_guard{*
this};
453 execute_one_operation<Operation>(event);
456 operation_queue_.invoke_and_pop_all(*
this);
460 execute_one_operation<Operation>(event);
464 template<
class Event>
465 MAKI_NOINLINE
void push_event_no_catch(
const Event& event)
467 static_assert(impl_of(
conf).run_to_completion);
468 push_event_impl<detail::machine_operation::process_event>(event);
471 template<detail::machine_operation Operation,
class Event>
472 void push_event_impl(
const Event& event)
474 operation_queue_.template push<any_event_visitor<Operation>>(event);
484 void process_pending_events()
486 if(!executing_operation_)
488 auto grd = executing_operation_guard{*
this};
489 operation_queue_.invoke_and_pop_all(*
this);
493 template<detail::machine_operation Operation>
494 struct any_event_visitor
496 template<
class Event>
497 static void call(
const Event& event,
machine& self)
499 self.execute_one_operation<Operation>(event);
503 template<detail::machine_operation Operation,
class Event>
504 void execute_one_operation(
const Event& event)
506 if constexpr(Operation == detail::machine_operation::start)
508 impl_.call_entry_action(*
this,
context(), event);
510 else if constexpr(Operation == detail::machine_operation::stop)
512 impl_.exit_to_finals(*
this,
context(), event);
516 constexpr auto has_matching_pre_processing_hook = detail::tlu::contains_if_v
518 pre_processing_hook_ptr_constant_list,
519 detail::event_action_traits::for_event<Event>::template has_containing_event_set
522 constexpr auto has_matching_post_processing_hook = detail::tlu::contains_if_v
524 post_processing_hook_ptr_constant_list,
525 detail::event_action_traits::for_event<Event>::template has_containing_event_set
529 if constexpr(has_matching_pre_processing_hook)
533 detail::call_matching_event_action<pre_processing_hook_ptr_constant_list>
547 if constexpr(has_matching_post_processing_hook)
551 auto processed =
false;
552 impl_.template call_internal_action<false>(*
this,
context(), event, processed);
553 detail::call_matching_event_action<post_processing_hook_ptr_constant_list>
570 impl_.template call_internal_action<false>(*
this,
context(), event);
575 static constexpr auto pre_processing_hooks = impl_of(
conf).pre_processing_hooks;
576 static constexpr auto post_processing_hooks = impl_of(
conf).post_processing_hooks;
577 static constexpr auto path = detail::path{};
579 using pre_processing_hook_ptr_constant_list = detail::tuple_to_element_ptr_constant_list_t<pre_processing_hooks>;
580 using post_processing_hook_ptr_constant_list = detail::tuple_to_element_ptr_constant_list_t<post_processing_hooks>;
582 detail::context_holder<
context_type, impl_of(
conf).context_sig> ctx_holder_;
583 detail::state_impls::composite_no_context<&conf, path> impl_;
584 bool executing_operation_ =
false;
585 operation_queue_type operation_queue_;