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)
124 execute_operation_now<detail::machine_operation::start>(
events::start{});
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))
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& StateBuilder>
329 [[nodiscard]]
const auto&
state()
const
339 template<const auto& StateBuilder>
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,
391 template<
class Event>
392 void start_no_catch(
const Event& event)
396 execute_operation<detail::machine_operation::start>(event);
400 template<
class Event>
401 void stop_no_catch(
const Event& event)
405 execute_operation<detail::machine_operation::stop>(event);
409 template<
class Event>
410 void process_event_now_no_catch(
const Event& event)
414 impl_of(
conf).process_event_now_enabled,
415 "`maki::machine_conf::process_event_now_enabled()` hasn't been set to `true`"
417 execute_operation_now<detail::machine_operation::process_event>(event);
420 template<detail::machine_operation Operation,
class Event>
421 void execute_operation(
const Event& event)
423 if constexpr(impl_of(
conf).run_to_completion)
425 if(!executing_operation_)
427 execute_operation_now<Operation>(event);
432 push_event_impl<Operation>(event);
437 execute_one_operation<Operation>(event);
441 template<detail::machine_operation Operation,
class Event>
442 void execute_operation_now(
const Event& event)
444 if constexpr(impl_of(
conf).run_to_completion)
446 auto grd = executing_operation_guard{*
this};
448 execute_one_operation<Operation>(event);
451 operation_queue_.invoke_and_pop_all(*
this);
455 execute_one_operation<Operation>(event);
459 template<
class Event>
460 MAKI_NOINLINE
void push_event_no_catch(
const Event& event)
462 static_assert(impl_of(
conf).run_to_completion);
463 push_event_impl<detail::machine_operation::process_event>(event);
466 template<detail::machine_operation Operation,
class Event>
467 void push_event_impl(
const Event& event)
469 operation_queue_.template push<any_event_visitor<Operation>>(event);
479 void process_pending_events()
481 if(!executing_operation_)
483 auto grd = executing_operation_guard{*
this};
484 operation_queue_.invoke_and_pop_all(*
this);
488 template<detail::machine_operation Operation>
489 struct any_event_visitor
491 template<
class Event>
492 static void call(
const Event& event,
machine& self)
494 self.execute_one_operation<Operation>(event);
498 template<detail::machine_operation Operation,
class Event>
499 void execute_one_operation(
const Event& event)
501 if constexpr(Operation == detail::machine_operation::start)
503 impl_.call_entry_action(*
this,
context(), event);
505 else if constexpr(Operation == detail::machine_operation::stop)
507 impl_.exit_to_finals(*
this,
context(), event);
511 constexpr auto has_matching_pre_processing_hook = detail::tlu::contains_if_v
513 pre_processing_hook_ptr_constant_list,
514 detail::event_action_traits::for_event<Event>::template has_containing_event_set
517 constexpr auto has_matching_post_processing_hook = detail::tlu::contains_if_v
519 post_processing_hook_ptr_constant_list,
520 detail::event_action_traits::for_event<Event>::template has_containing_event_set
524 if constexpr(has_matching_pre_processing_hook)
528 detail::call_matching_event_action<pre_processing_hook_ptr_constant_list>
542 if constexpr(has_matching_post_processing_hook)
546 auto processed =
false;
547 impl_.template call_internal_action<false>(*
this,
context(), event, processed);
548 detail::call_matching_event_action<post_processing_hook_ptr_constant_list>
565 impl_.template call_internal_action<false>(*
this,
context(), event);
570 static constexpr auto pre_processing_hooks = impl_of(
conf).pre_processing_hooks;
571 static constexpr auto post_processing_hooks = impl_of(
conf).post_processing_hooks;
572 static constexpr auto path = detail::path{};
574 using pre_processing_hook_ptr_constant_list = detail::tuple_to_element_ptr_constant_list_t<pre_processing_hooks>;
575 using post_processing_hook_ptr_constant_list = detail::tuple_to_element_ptr_constant_list_t<post_processing_hooks>;
577 detail::context_holder<
context_type, impl_of(
conf).context_sig> ctx_holder_;
578 detail::state_impls::composite_no_context<&conf, path> impl_;
579 bool executing_operation_ =
false;
580 operation_queue_type operation_queue_;