84 static constexpr const auto&
conf = Conf;
86#ifndef MAKI_DETAIL_DOXYGEN
87 using option_set_type = std::decay_t<
decltype(impl_of(
conf))>;
90#ifdef MAKI_DETAIL_DOXYGEN
96 using context_type =
typename option_set_type::context_type;
101 detail::is_machine_conf_v<std::decay_t<
decltype(
conf)>>,
102 "Given `Conf` must be an instance of `maki::machine_conf`"
117 template<
class... ContextArgs>
119 ctx_holder_(*this, std::forward<ContextArgs>(ctx_args)...),
122 if constexpr(impl_of(
conf).auto_start)
124 MAKI_DETAIL_MAYBE_CATCH(start_now())
139 return ctx_holder_.get();
147 return ctx_holder_.get();
157 return !impl_.completed();
171 template<
class Event = events::start>
174 MAKI_DETAIL_MAYBE_CATCH(start_no_catch(event))
185 template<
class Event = events::stop>
186 void stop(
const Event& event = {})
188 MAKI_DETAIL_MAYBE_CATCH(stop_no_catch(event))
240 template<
class Event>
250 template<
class Event>
253 execute_operation<detail::machine_operation::process_event>(event);
275 template<
class Event>
278 MAKI_DETAIL_MAYBE_CATCH(process_event_now_no_catch(event))
292 template<
class Event>
295 return impl_.template call_internal_action<true>(*
this,
context(), event);
308 template<
class Event>
311 MAKI_DETAIL_MAYBE_CATCH(push_event_no_catch(event))
327 template<const auto& StateMold>
328 [[nodiscard]]
const auto&
state()
const
338 template<const auto& StateMold>
339 [[nodiscard]]
bool is()
const
345 class executing_operation_guard
348 executing_operation_guard(
machine& self):
351 self_.executing_operation_ =
true;
354 executing_operation_guard(
const executing_operation_guard&) =
delete;
355 executing_operation_guard(executing_operation_guard&&) =
delete;
356 executing_operation_guard& operator=(
const executing_operation_guard&) =
delete;
357 executing_operation_guard& operator=(executing_operation_guard&&) =
delete;
359 ~executing_operation_guard()
361 self_.executing_operation_ =
false;
368 struct real_operation_queue_holder
370 template<
bool = true>
371 using type = detail::function_queue
374 impl_of(
conf).small_event_max_size,
375 impl_of(
conf).small_event_max_align
380 template<
bool = true>
383 using operation_queue_type =
typename std::conditional_t
385 impl_of(
conf).run_to_completion,
386 real_operation_queue_holder,
392 execute_operation_now<detail::machine_operation::start>(
events::start{});
395 template<
class Event>
396 void start_no_catch(
const Event& event)
400 execute_operation<detail::machine_operation::start>(event);
404 template<
class Event>
405 void stop_no_catch(
const Event& event)
409 execute_operation<detail::machine_operation::stop>(event);
413 template<
class Event>
414 void process_event_now_no_catch(
const Event& event)
418 impl_of(
conf).process_event_now_enabled,
419 "`maki::machine_conf::process_event_now_enabled()` hasn't been set to `true`"
421 execute_operation_now<detail::machine_operation::process_event>(event);
424 template<detail::machine_operation Operation,
class Event>
425 void execute_operation(
const Event& event)
427 if constexpr(impl_of(
conf).run_to_completion)
429 if(!executing_operation_)
431 execute_operation_now<Operation>(event);
436 push_event_impl<Operation>(event);
441 execute_one_operation<Operation>(event);
445 template<detail::machine_operation Operation,
class Event>
446 void execute_operation_now(
const Event& event)
448 if constexpr(impl_of(
conf).run_to_completion)
450 auto grd = executing_operation_guard{*
this};
452 execute_one_operation<Operation>(event);
455 operation_queue_.invoke_and_pop_all(*
this);
459 execute_one_operation<Operation>(event);
463 template<
class Event>
464 MAKI_NOINLINE
void push_event_no_catch(
const Event& event)
466 static_assert(impl_of(
conf).run_to_completion);
467 push_event_impl<detail::machine_operation::process_event>(event);
470 template<detail::machine_operation Operation,
class Event>
471 void push_event_impl(
const Event& event)
473 operation_queue_.template push<any_event_visitor<Operation>>(event);
483 void process_pending_events()
485 if(!executing_operation_)
487 auto grd = executing_operation_guard{*
this};
488 operation_queue_.invoke_and_pop_all(*
this);
492 template<detail::machine_operation Operation>
493 struct any_event_visitor
495 template<
class Event>
496 static void call(
const Event& event,
machine& self)
498 self.execute_one_operation<Operation>(event);
502 template<detail::machine_operation Operation,
class Event>
503 void execute_one_operation(
const Event& event)
505 if constexpr(Operation == detail::machine_operation::start)
507 impl_.enter(*
this,
context(), event);
509 else if constexpr(Operation == detail::machine_operation::stop)
511 impl_.exit_to_finals(*
this,
context(), event);
515 constexpr auto has_matching_pre_processing_hook = detail::tlu::contains_if_v
517 pre_processing_hook_ptr_constant_list,
518 detail::event_action_traits::for_event<Event>::template has_containing_event_set
521 constexpr auto has_matching_post_processing_hook = detail::tlu::contains_if_v
523 post_processing_hook_ptr_constant_list,
524 detail::event_action_traits::for_event<Event>::template has_containing_event_set
528 if constexpr(has_matching_pre_processing_hook)
532 detail::call_matching_event_action<pre_processing_hook_ptr_constant_list>
546 if constexpr(has_matching_post_processing_hook)
550 const auto processed = impl_.template call_internal_action<false>(*
this,
context(), event);
551 detail::call_matching_event_action<post_processing_hook_ptr_constant_list>
568 impl_.template call_internal_action<false>(*
this,
context(), event);
573 static constexpr auto pre_processing_hooks = impl_of(
conf).pre_processing_hooks;
574 static constexpr auto post_processing_hooks = impl_of(
conf).post_processing_hooks;
575 static constexpr auto path = detail::path_impl{};
577 using pre_processing_hook_ptr_constant_list = detail::mix_constant_list_t<pre_processing_hooks>;
578 using post_processing_hook_ptr_constant_list = detail::mix_constant_list_t<post_processing_hooks>;
580 detail::context_holder
583 detail::context_storage::plain,
584 impl_of(
conf).context_sig
586 detail::state_impls::composite_no_context
590 detail::context_storage::plain
592 bool executing_operation_ =
false;
593 operation_queue_type operation_queue_;