9 #if defined(_MSC_VER) && !defined(__clang__) 10 #define COMPILING_WITH_MSVC 12 #if (__cplusplus < 201305L && _MSC_VER < 1900) 13 #error "[Boost].SML requires C++14 support (Clang-3.4+, GCC-5.1+, MSVC-2015+)" 15 #define BOOST_SML_VERSION 1'1'0 16 #define BOOST_SML_NAMESPACE_BEGIN \ 19 inline namespace v1_1_0 { 20 #define BOOST_SML_NAMESPACE_END \ 24 #if defined(__clang__) 25 #define __BOOST_SML_UNUSED __attribute__((unused)) 26 #define __BOOST_SML_VT_INIT \ 28 #define __BOOST_SML_ZERO_SIZE_ARRAY(...) __VA_ARGS__ _[0] 29 #define __BOOST_SML_ZERO_SIZE_ARRAY_CREATE(...) 30 #define __BOOST_SML_TEMPLATE_KEYWORD template 31 #pragma clang diagnostic push 32 #pragma clang diagnostic ignored "-Wgnu-string-literal-operator-template" 33 #pragma clang diagnostic ignored "-Wzero-length-array" 34 #elif defined(__GNUC__) 35 #if !defined(__has_builtin) 36 #define __has_builtin(...) 0 38 #define __BOOST_SML_UNUSED __attribute__((unused)) 39 #define __BOOST_SML_VT_INIT \ 41 #define __BOOST_SML_ZERO_SIZE_ARRAY(...) __VA_ARGS__ _[0] 42 #define __BOOST_SML_ZERO_SIZE_ARRAY_CREATE(...) __VA_ARGS__ ? __VA_ARGS__ : 1 43 #define __BOOST_SML_TEMPLATE_KEYWORD template 44 #pragma GCC diagnostic push 45 #pragma GCC diagnostic ignored "-Wpedantic" 46 #elif defined(COMPILING_WITH_MSVC) 47 #define __has_builtin(...) __has_builtin##__VA_ARGS__ 48 #define __has_builtin__make_integer_seq(...) 1 49 #define __BOOST_SML_UNUSED 50 #define __BOOST_SML_VT_INIT 51 #define __BOOST_SML_ZERO_SIZE_ARRAY(...) 52 #define __BOOST_SML_ZERO_SIZE_ARRAY_CREATE(...) __VA_ARGS__ ? __VA_ARGS__ : 1 53 #if (defined(COMPILING_WITH_MSVC) && _MSC_VER >= 1910) // MSVC 2017 54 #define __BOOST_SML_TEMPLATE_KEYWORD template 56 #define __BOOST_SML_TEMPLATE_KEYWORD 58 #pragma warning(disable : 4503) 59 #pragma warning(disable : 4200) 61 BOOST_SML_NAMESPACE_BEGIN
62 #define __BOOST_SML_REQUIRES(...) typename aux::enable_if<__VA_ARGS__, int>::type = 0 64 using byte =
unsigned char;
70 template <
class,
class>
74 using type = type_list;
78 using type = bool_list;
80 template <
class... Ts>
81 struct inherit : Ts... {
90 template <
class T, T V>
91 struct integral_constant {
92 using type = integral_constant;
93 static constexpr T value = V;
95 using true_type = integral_constant<bool, true>;
96 using false_type = integral_constant<bool, false>;
97 template <
class... Ts>
100 struct always : true_type {};
102 struct never : false_type {};
103 template <
bool B,
class T,
class F>
107 template <
class T,
class F>
108 struct conditional<false, T, F> {
111 template <
bool B,
class T,
class F>
113 template <
bool B,
class T =
void>
116 struct enable_if<true, T> {
119 template <
bool B,
class T =
void>
121 template <
class,
class>
122 struct is_same : false_type {};
124 struct is_same<T, T> : true_type {};
125 template <
class T,
class U>
126 #if defined(COMPILING_WITH_MSVC) 127 struct is_base_of : integral_constant<bool, __is_base_of(T, U)> {
130 using is_base_of = integral_constant<bool, __is_base_of(T, U)>;
132 template <
class T,
class... TArgs>
133 decltype(T(declval<TArgs>()...), true_type{}) test_is_constructible(
int);
134 template <
class,
class...>
135 false_type test_is_constructible(...);
136 template <
class T,
class... TArgs>
137 #if defined(COMPILING_WITH_MSVC) 138 struct is_constructible : decltype(test_is_constructible<T, TArgs...>(0)) {
141 using is_constructible = decltype(test_is_constructible<T, TArgs...>(0));
143 template <
class T,
class U>
144 struct is_empty_base : T {
148 struct is_empty : aux::integral_constant<bool, sizeof(is_empty_base<T, none_type>) == sizeof(none_type)> {};
150 struct function_traits;
151 template <
class R,
class... TArgs>
152 struct function_traits<R (*)(TArgs...)> {
153 using args = type_list<TArgs...>;
155 template <
class R,
class... TArgs>
156 struct function_traits<R(TArgs...)> {
157 using args = type_list<TArgs...>;
159 template <
class R,
class T,
class... TArgs>
160 struct function_traits<R (T::*)(TArgs...)> {
161 using args = type_list<TArgs...>;
163 template <
class R,
class T,
class... TArgs>
164 struct function_traits<R (T::*)(TArgs...) const> {
165 using args = type_list<TArgs...>;
167 #if __cplusplus > 201402L && __cpp_noexcept_function_type >= 201510 168 template <
class R,
class... TArgs>
169 struct function_traits<R (*)(TArgs...) noexcept> {
170 using args = type_list<TArgs...>;
172 template <
class R,
class... TArgs>
173 struct function_traits<R(TArgs...) noexcept> {
174 using args = type_list<TArgs...>;
176 template <
class R,
class T,
class... TArgs>
177 struct function_traits<R (T::*)(TArgs...) noexcept> {
178 using args = type_list<TArgs...>;
180 template <
class R,
class T,
class... TArgs>
181 struct function_traits<R (T::*)(TArgs...) const noexcept> {
182 using args = type_list<TArgs...>;
186 using function_traits_t =
typename function_traits<T>::args;
188 struct remove_const {
192 struct remove_const<const T> {
198 struct remove_reference {
202 struct remove_reference<T &> {
206 struct remove_reference<T &&> {
213 using swallow =
int[];
215 struct index_sequence {
216 using type = index_sequence;
218 #if __has_builtin(__make_integer_seq) 219 template <
class T, T...>
220 struct integer_sequence;
222 struct integer_sequence<int, Ns...> {
223 using type = index_sequence<Ns...>;
226 struct make_index_sequence_impl {
230 template <
class,
class>
232 template <
int... I1,
int... I2>
233 struct concat<index_sequence<I1...>, index_sequence<I2...>> : index_sequence<I1..., (sizeof...(I1) + I2)...> {};
235 struct make_index_sequence_impl
236 : concat<typename make_index_sequence_impl<N / 2>::type, typename make_index_sequence_impl<N - N / 2>::type>
::type {};
238 struct make_index_sequence_impl<0> : index_sequence<> {};
240 struct make_index_sequence_impl<1> : index_sequence<0> {};
246 using type = type_list<>;
252 template <
class... Ts>
253 struct join<type_list<Ts...>> : type_list<Ts...> {};
254 template <
class... T1s,
class... T2s>
255 struct join<type_list<T1s...>, type_list<T2s...>> : type_list<T1s..., T2s...> {};
256 template <
class... T1s,
class... T2s,
class... T3s>
257 struct join<type_list<T1s...>, type_list<T2s...>, type_list<T3s...>> : type_list<T1s..., T2s..., T3s...> {};
258 template <
class... T1s,
class... T2s,
class... Ts>
259 struct join<type_list<T1s...>, type_list<T2s...>, Ts...> : join<type_list<T1s..., T2s...>, Ts...> {};
260 template <
class... Ts,
class... T1s,
class... T2s,
class... T3s,
class... T4s,
class... T5s,
class... T6s,
class... T7s,
261 class... T8s,
class... T9s,
class... T10s,
class... T11s,
class... T12s,
class... T13s,
class... T14s,
class... T15s,
262 class... T16s,
class... Us>
263 struct join<type_list<Ts...>, type_list<T1s...>, type_list<T2s...>, type_list<T3s...>, type_list<T4s...>, type_list<T5s...>,
264 type_list<T6s...>, type_list<T7s...>, type_list<T8s...>, type_list<T9s...>, type_list<T10s...>, type_list<T11s...>,
265 type_list<T12s...>, type_list<T13s...>, type_list<T14s...>, type_list<T15s...>, type_list<T16s...>, Us...>
266 : join<type_list<Ts..., T1s..., T2s..., T3s..., T4s..., T5s..., T6s..., T7s..., T8s..., T9s..., T10s..., T11s..., T12s...,
267 T13s..., T14s..., T15s..., T16s...>,
269 template <
class... TArgs>
270 using join_t =
typename join<TArgs...>
::type;
271 template <
class,
class...>
273 template <
class T1,
class T2,
class... Rs,
class... Ts>
274 struct unique_impl<
type<T1, Rs...>, T2, Ts...>
275 : conditional_t<is_base_of<type<T2>, T1>::value, unique_impl<type<inherit<T1>, Rs...>, Ts...>,
276 unique_impl<type<inherit<T1, type<T2>>, Rs..., T2>, Ts...>> {};
277 template <
class T1,
class... Rs>
278 struct unique_impl<
type<T1, Rs...>> : type_list<Rs...> {};
279 template <
class... Ts>
280 struct unique : unique_impl<type<none_type>, Ts...> {};
282 struct unique<T> : type_list<T> {};
283 template <
class... Ts>
284 using unique_t =
typename unique<Ts...>
::type;
285 template <
class,
class...>
288 struct is_unique<T> : true_type {};
289 template <
class T1,
class T2,
class... Ts>
290 struct is_unique<T1, T2, Ts...>
291 : conditional_t<is_base_of<type<T2>, T1>::value, false_type, is_unique<inherit<T1, type<T2>>, Ts...>> {};
292 template <
class... Ts>
293 using is_unique_t = is_unique<none_type, Ts...>;
294 template <
template <
class...>
class,
class>
296 template <
template <
class...>
class T,
template <
class...>
class U,
class... Ts>
297 struct apply<T, U<Ts...>> {
298 using type = T<Ts...>;
300 template <
template <
class...>
class T,
class D>
302 template <
int,
class T>
304 explicit tuple_type(
const T &
object) : value(object) {}
307 template <
class,
class...>
309 template <
int... Ns,
class... Ts>
310 struct tuple_impl<index_sequence<Ns...>, Ts...> : tuple_type<Ns, Ts>... {
311 explicit tuple_impl(Ts... ts) : tuple_type<Ns, Ts>(ts)... {}
314 struct tuple_impl<index_sequence<0>> {
315 __BOOST_SML_ZERO_SIZE_ARRAY(byte);
317 template <
class... Ts>
318 using tuple = tuple_impl<make_index_sequence<
sizeof...(Ts)>, Ts...>;
319 template <int N, class T>
320 T &get_by_id(tuple_type<N, T> *
object) {
321 return static_cast<tuple_type<N, T> &
>(*object).value;
324 struct pool_type_base {
325 __BOOST_SML_ZERO_SIZE_ARRAY(byte);
328 struct pool_type : pool_type_base {
329 explicit pool_type(T
object) : value{
object} {}
330 template <
class TObject>
331 pool_type(init i, TObject
object) : value{i,
object} {}
335 struct missing_ctor_parameter {
336 static constexpr
auto value =
false;
337 auto operator()()
const {
return T{}(); }
338 template <class U, __BOOST_SML_REQUIRES(!aux::is_base_of<pool_type_base, U>::value && aux::is_constructible<U>::value)>
342 #if !defined(COMPILING_WITH_MSVC) 343 template <class TMissing, __BOOST_SML_REQUIRES(!aux::is_base_of<pool_type_base, TMissing>::value)>
344 operator TMissing &()
const {
345 static_assert(missing_ctor_parameter<TMissing>::value,
346 "State Machine is missing a constructor parameter! Check out the `missing_ctor_parameter` error to see the " 352 missing_ctor_parameter<T> try_get(...) {
356 T try_get(
const pool_type<T> *
object) {
357 return object->value;
360 const T &try_get(
const pool_type<const T &> *
object) {
361 return object->value;
364 T &try_get(
const pool_type<T &> *
object) {
365 return object->value;
367 template <
class T,
class TPool>
369 return static_cast<pool_type<T> &
>(p).value;
371 template <
class T,
class TPool>
372 const T &cget(
const TPool &p) {
373 return static_cast<const pool_type<T> &
>(p).value;
375 template <
class... Ts>
376 struct pool : pool_type<Ts>... {
377 using boost_di_inject__ = type_list<Ts...>;
379 explicit pool(Ts... ts) : pool_type<Ts>(ts)... {}
380 template <
class... TArgs>
381 pool(init,
const pool<TArgs...> &p) : pool_type<Ts>(try_get<aux::remove_const_t<aux::remove_reference_t<Ts>>>(&p))... {}
382 template <
class... TArgs>
383 pool(
const pool<TArgs...> &p) : pool_type<Ts>(init{}, p)... {}
387 using boost_di_inject__ = type_list<>;
389 template <
class... Ts>
390 explicit pool(Ts &&...) {}
391 __BOOST_SML_ZERO_SIZE_ARRAY(byte);
393 template <
int,
class>
394 struct type_id_type {};
395 template <
class,
class...>
397 template <
int... Ns,
class... Ts>
398 struct type_id_impl<index_sequence<Ns...>, Ts...> : type_id_type<Ns, Ts>... {};
399 template <
class... Ts>
400 struct type_id : type_id_impl<make_index_sequence<sizeof...(Ts)>, Ts...> {};
401 template <
class R,
class T,
int N>
402 constexpr R get_id(type_id_type<N, T> *) {
403 return static_cast<R
>(N);
405 template <
template <
class...>
class,
class T>
406 struct is : false_type {};
407 template <
template <
class...>
class T,
class... Ts>
408 struct is<T, T<Ts...>> : true_type {};
411 template <
template <
class...>
class T,
class... Ts>
412 struct size<T<Ts...>> {
413 static constexpr
auto value =
sizeof...(Ts);
415 #if defined(COMPILING_WITH_MSVC) 416 constexpr
int max_impl() {
return 0; }
417 constexpr
int max_impl(
int r) {
return r; }
418 constexpr
int max_impl(
int r,
int i) {
return r > i ? r : i; }
419 constexpr
int max_impl(
int r,
int i,
int ints...) {
return i > r ? max_impl(i, ints) : max_impl(r, ints); }
421 constexpr
int max() {
422 return max_impl(Ts...);
426 constexpr
int max() {
428 (void)swallow{0, (Ts > max ? max = Ts : max)...};
432 template <
class TExpr,
class =
void>
433 struct zero_wrapper : TExpr {
435 explicit zero_wrapper(
const TExpr &expr) : TExpr(expr) {}
436 const TExpr &
get()
const {
return *
this; }
438 template <
class,
class>
439 struct zero_wrapper_impl;
440 template <
class TExpr,
class... TArgs>
441 struct zero_wrapper_impl<TExpr, type_list<TArgs...>> {
442 auto operator()(TArgs... args)
const {
return reinterpret_cast<const TExpr &
>(*this)(args...); }
443 __BOOST_SML_ZERO_SIZE_ARRAY(byte);
445 template <
class TExpr>
446 struct zero_wrapper<TExpr, void_t<decltype(+declval<TExpr>())>>
447 : zero_wrapper_impl<TExpr, function_traits_t<decltype(&TExpr::operator())>> {
449 template <
class... Ts>
450 zero_wrapper(Ts &&...) {}
451 const TExpr &
get()
const {
return reinterpret_cast<const TExpr &
>(*this); }
454 template <
class,
int N,
int... Ns>
455 auto get_type_name(
const char *ptr, index_sequence<Ns...>) {
456 static const char str[] = {ptr[N + Ns]..., 0};
461 const char *get_type_name() {
462 #if defined(COMPILING_WITH_MSVC) 463 return detail::get_type_name<T, 34>(__FUNCSIG__, make_index_sequence<
sizeof(__FUNCSIG__) - 34 - 8>{});
464 #elif defined(__clang__) 465 return detail::get_type_name<T, 58>(__PRETTY_FUNCTION__, make_index_sequence<
sizeof(__PRETTY_FUNCTION__) - 58 - 2>{});
466 #elif defined(__GNUC__) 467 return detail::get_type_name<T, 63>(__PRETTY_FUNCTION__, make_index_sequence<
sizeof(__PRETTY_FUNCTION__) - 63 - 2>{});
470 template <
class T, T...>
472 template <
char... Chrs>
473 struct string<char, Chrs...> {
475 static auto c_str() {
476 static constexpr
char str[] = {Chrs..., 0};
483 static auto c_str() {
return c_str_impl((T *)0); }
485 static decltype(U::c_str()) c_str_impl(U *) {
488 static auto c_str_impl(...) {
return get_type_name<T>(); }
493 struct defer_queue_policy__ {};
494 template <
template <
class...>
class T>
495 struct defer_queue : aux::pair<back::policies::defer_queue_policy__, defer_queue<T>> {
503 template <
class... Ts>
505 using ids_t = aux::type_id<Ts...>;
506 static constexpr
auto alignment = aux::max<
alignof(Ts)...>();
507 static constexpr
auto size = aux::max<
sizeof(Ts)...>();
509 static void dtor_impl(aux::byte *data) {
511 reinterpret_cast<T *
>(data)->~T();
514 static void move_impl(aux::byte (&data)[size], queue_event &&other) {
515 new (&data) T(static_cast<T &&>(*reinterpret_cast<T *>(other.data)));
519 queue_event(queue_event &&other) : id(other.id), dtor(other.dtor), move(other.move) {
520 move(data, static_cast<queue_event &&>(other));
522 queue_event &operator=(queue_event &&other) {
528 move(data, static_cast<queue_event &&>(other));
531 queue_event(
const queue_event &) =
delete;
532 queue_event &operator=(
const queue_event &) =
delete;
534 queue_event(T
object) {
535 id = aux::get_id<int, T>((ids_t *)0);
536 dtor = &dtor_impl<T>;
537 move = &move_impl<T>;
538 new (&data) T(static_cast<T &&>(
object));
540 ~queue_event() { dtor(data); }
541 alignas(alignment) aux::byte data[size];
545 void (*dtor)(aux::byte *);
546 void (*move)(aux::byte (&)[size], queue_event &&);
548 template <
class TEvent>
549 class queue_event_call {
550 using call_t = void (*)(
void *,
const TEvent &);
553 queue_event_call() =
default;
554 explicit queue_event_call(
const call_t &call) : call{call} {}
557 template <
class... TEvents>
558 struct queue_handler : queue_event_call<TEvents>... {
559 queue_handler() =
default;
560 template <
class TQueue,
class =
typename TQueue::container_type>
561 explicit queue_handler(TQueue &queue)
562 : queue_event_call<TEvents>(queue_handler::push_impl<TQueue, TEvents>)..., queue_{&queue} {}
563 template <
class TEvent>
564 void operator()(
const TEvent &event) {
565 static_cast<queue_event_call<TEvent> *
>(
this)->call(queue_, event);
569 template <
class TQueue,
class TEvent>
570 static auto push_impl(
void *queue,
const TEvent &event) {
571 static_cast<TQueue *
>(queue)->push(event);
575 template <
class... TEvents>
576 struct deque_handler : queue_event_call<TEvents>... {
577 deque_handler() =
default;
578 template <
class TDeque,
class =
typename TDeque::allocator_type>
579 explicit deque_handler(TDeque &deque)
580 : queue_event_call<TEvents>(deque_handler::push_impl<TDeque, TEvents>)..., deque_{&deque} {}
581 template <
class TEvent>
582 void operator()(
const TEvent &event) {
583 static_cast<queue_event_call<TEvent> *
>(
this)->call(deque_, event);
587 template <
class TDeque,
class TEvent>
588 static auto push_impl(
void *deque,
const TEvent &event) {
589 static_cast<TDeque *
>(deque)->push_back(event);
597 struct unexpected {};
598 struct entry_exit {};
599 struct terminate_state {
600 static auto c_str() {
return "terminate"; }
602 struct internal_event {
603 static auto c_str() {
return "internal_event"; }
605 struct anonymous : internal_event {
606 static auto c_str() {
return "anonymous"; }
608 template <
class T,
class TEvent = T>
609 struct on_entry : internal_event, entry_exit {
610 static auto c_str() {
return "on_entry"; }
611 explicit on_entry(
const TEvent &event = {}) : event_(event) {}
612 const TEvent &event_;
614 template <
class T,
class TEvent = T>
615 struct on_exit : internal_event, entry_exit {
616 static auto c_str() {
return "on_exit"; }
617 explicit on_exit(
const TEvent &event = {}) : event_(event) {}
618 const TEvent &event_;
620 template <
class T,
class TException = T>
621 struct exception : internal_event {
622 using type = TException;
623 explicit exception(
const TException &exception = {}) : exception_(exception) {}
624 const TException &exception_;
626 template <
class T,
class TEvent = T>
627 struct unexpected_event : internal_event, unexpected {
628 explicit unexpected_event(
const TEvent &event = {}) : event_(event) {}
629 const TEvent &event_;
631 template <
class TEvent>
633 using event_t = TEvent;
634 using generic_t = TEvent;
635 using mapped_t = void;
637 template <
class TEvent>
638 struct event_type<exception<TEvent>> {
639 using event_t = TEvent;
640 using generic_t = exception<TEvent>;
641 using mapped_t = void;
643 template <
class TEvent,
class T>
644 struct event_type<unexpected_event<T, TEvent>> {
645 using event_t = TEvent;
646 using generic_t = unexpected_event<T>;
647 using mapped_t = void;
649 template <
class TEvent,
class T>
650 struct event_type<on_entry<T, TEvent>> {
651 using event_t = TEvent;
652 using generic_t = on_entry<T>;
653 using mapped_t = on_entry<T, TEvent>;
655 template <
class TEvent,
class T>
656 struct event_type<on_exit<T, TEvent>> {
657 using event_t = TEvent;
658 using generic_t = on_exit<T>;
659 using mapped_t = on_exit<T, TEvent>;
661 template <
class TEvent>
662 using get_event_t =
typename event_type<TEvent>::event_t;
663 template <
class TEvent>
664 using get_generic_t =
typename event_type<TEvent>::generic_t;
665 template <
class TEvent>
666 using get_mapped_t =
typename event_type<TEvent>::mapped_t;
667 template <
class... TEvents>
668 struct process : queue_handler<TEvents...> {
669 using queue_handler<TEvents...>::queue_handler;
671 template <
class... TEvents>
672 struct defer : deque_handler<TEvents...> {
673 using deque_handler<TEvents...>::deque_handler;
681 template <
class,
class...>
683 template <
class TEvent>
684 using get_event = aux::conditional_t<aux::is_base_of<internal_event, TEvent>::value, aux::type_list<>, aux::type_list<TEvent>>;
685 template <
class,
class,
class TEvent>
686 struct get_all_events_impl {
687 using type = get_event<TEvent>;
689 template <
class TSrc,
class TDst,
class TEvent>
690 struct get_all_events_impl<TSrc, TDst, unexpected_event<TEvent>> {
691 using type = aux::type_list<TEvent>;
693 template <
class TSrc,
class TDst,
class TEvent>
694 struct get_all_events_impl<sm<TSrc>, TDst, TEvent> {
695 using type = aux::join_t<get_event<TEvent>,
typename sm<TSrc>::events>;
697 template <
class TSrc,
class TDst,
class TEvent>
698 struct get_all_events_impl<TSrc, sm<TDst>, TEvent> {
699 using type = aux::join_t<get_event<TEvent>,
typename sm<TDst>::events>;
701 template <
class TSrc,
class TDst,
class TEvent>
702 struct get_all_events_impl<sm<TSrc>, sm<TDst>, TEvent> {
703 using type = aux::join_t<get_event<TEvent>,
typename sm<TSrc>::events,
typename sm<TDst>::events>;
705 template <
class,
class TEvent>
706 struct get_sub_internal_events_impl {
707 using type = aux::conditional_t<aux::is_base_of<internal_event, TEvent>::value, aux::type_list<TEvent>, aux::type_list<>>;
709 template <
class T,
class TEvent>
710 struct get_sub_internal_events_impl<sm<T>, TEvent> {
711 using type = aux::join_t<aux::type_list<TEvent>,
typename sm_impl<T>::sub_internal_events_t>;
713 template <
class... Ts>
714 using get_all_events =
716 template <
class... Ts>
717 using get_sub_internal_events =
720 template <
class... Ts>
721 using get_events = aux::type_list<
typename Ts::event...>;
723 struct get_exception : aux::type_list<> {};
725 struct get_exception<exception<T>> : aux::type_list<exception<T>> {};
726 template <
class... Ts>
728 template <
class... Ts>
729 using get_states = aux::join_t<aux::type_list<typename Ts::src_state, typename Ts::dst_state>...>;
730 template <
class... Ts>
731 using get_initial_states =
732 aux::join_t<typename aux::conditional<Ts::initial, aux::type_list<typename Ts::src_state>, aux::type_list<>>
::type...>;
733 template <
class... Ts>
734 using get_history_states = aux::join_t<
735 typename aux::conditional<!Ts::history && Ts::initial, aux::type_list<typename Ts::src_state>, aux::type_list<>>
::type...>;
737 struct get_sub_sm : aux::type_list<> {};
739 struct get_sub_sm<sm<T>> : aux::join_t<aux::type_list<T>, typename sm<T>::state_machines> {};
740 template <
class... Ts>
742 template <
class... Ts>
743 using get_sm_t = aux::type_list<
typename Ts::sm...>;
744 template <
class... Ts>
745 using get_non_empty_t =
746 aux::join_t<typename aux::conditional<aux::is_empty<Ts>::value, aux::type_list<>, aux::type_list<Ts>>
::type...>;
747 template <
class... Ts>
748 using merge_deps = aux::join_t<
typename Ts::deps...>;
752 struct sub_sm<sm_impl<sm_policy<T>>> {
753 template <
class U,
class... TPolicies>
754 static sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>> &
get(
755 aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> *object) {
756 return static_cast<aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...
>>> &>(*object).value;
758 template <
class... TPolicies>
759 static sm_impl<sm_policy<T, TPolicies...>> &
get(aux::pool_type<sm_impl<sm_policy<T, TPolicies...>>> *object) {
760 return static_cast<aux::pool_type<sm_impl<sm_policy<T, TPolicies...
>>> &>(*object).value;
762 template <
class... TPolicies>
763 static const sm_impl<sm_policy<T, TPolicies...>> &cget(
const aux::pool_type<sm_impl<sm_policy<T, TPolicies...>>> *
object) {
764 return static_cast<const aux::pool_type<sm_impl<sm_policy<T, TPolicies...
>>> &>(*object).value;
767 template <
class T,
class U>
768 struct sub_sm<sm_impl<sm_policy<T, aux::identity<U>>>> {
769 template <
class... TPolicies>
770 static sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>> &
get(
771 aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> *object) {
772 return static_cast<aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...
>>> &>(*object).value;
774 template <
class... TPolicies>
775 static const sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>> &cget(
776 const aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...>>> *
object) {
777 return static_cast<const aux::pool_type<sm_impl<sm_policy<T, aux::identity<U>, TPolicies...
>>> &>(*object).value;
780 template <
class T,
class... TPolicies>
782 using type = sm_policy<T, TPolicies...>;
784 template <
class T,
class... TDetails,
class... TPolicies>
785 struct rebind_impl<sm_policy<T, TDetails...>, TPolicies...> {
786 using type = sm_policy<T, TDetails..., TPolicies...>;
788 template <
class T,
class... TDetails,
class... TPolicies>
789 struct rebind_impl<sm<sm_policy<T, TDetails...>>, TPolicies...> {
790 using type = sm_policy<T, TDetails..., TPolicies...>;
792 template <
class,
class>
793 struct convert_to_sm;
794 template <
class T,
class... Ts>
795 struct convert_to_sm<T, aux::type_list<Ts...>> {
796 using type = aux::type_list<sm_impl<T>, sm_impl<typename T::template rebind<Ts>>...>;
807 struct transitions_sub;
808 template <
class T,
class... Ts>
809 struct transitions<T, Ts...> {
810 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
811 static bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state) {
812 if (aux::get<T>(sm.transitions_).execute(event, sm, deps, subs, current_state,
typename SM::has_entry_exits{})) {
815 return transitions<Ts...>::execute(event, sm, deps, subs, current_state);
819 struct transitions<T> {
820 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
821 static bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state) {
822 return execute_impl(event, sm, deps, subs, current_state);
824 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
825 static bool execute_impl(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state) {
826 return aux::get<T>(sm.transitions_).execute(event, sm, deps, subs, current_state,
typename SM::has_entry_exits{});
828 template <
class _,
class TEvent,
class SM,
class TDeps,
class TSubs>
829 static bool execute_impl(
const on_exit<_, TEvent> &event, SM &sm, TDeps &deps, TSubs &subs,
830 typename SM::state_t ¤t_state) {
831 aux::get<T>(sm.transitions_).execute(event, sm, deps, subs, current_state,
typename SM::has_entry_exits{});
836 struct transitions<aux::true_type> {
837 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
838 static bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state) {
839 sm.process_internal_event(unexpected_event<TEvent>{
event}, deps, subs, current_state);
844 struct transitions<aux::false_type> {
845 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
846 static bool execute(
const TEvent &, SM &, TDeps &, TSubs &,
typename SM::state_t &) {
850 template <
class TSM,
class T,
class... Ts>
851 struct transitions_sub<sm<TSM>, T, Ts...> {
852 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
853 static bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state) {
854 return execute_impl(event, sm, deps, subs, current_state);
856 template <
class,
class SM,
class TDeps,
class TSubs>
857 static bool execute(
const anonymous &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state) {
858 if (sub_sm<sm_impl<TSM>>::cget(&subs).is_terminated()) {
859 const auto handled = sub_sm<sm_impl<TSM>>::get(&subs).process_event(event, deps, subs);
860 return handled ? handled : transitions<T, Ts...>::execute(event, sm, deps, subs, current_state);
864 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
865 static bool execute_impl(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state) {
866 const auto handled = sub_sm<sm_impl<TSM>>::get(&subs).process_event(event, deps, subs);
867 return handled ? handled : transitions<T, Ts...>::execute(event, sm, deps, subs, current_state);
869 template <
class _,
class TEvent,
class SM,
class TDeps,
class TSubs>
870 static bool execute_impl(
const back::on_entry<_, TEvent> &event, SM &sm, TDeps &deps, TSubs &subs,
871 typename SM::state_t ¤t_state) {
872 transitions<T, Ts...>::execute(event, sm, deps, subs, current_state);
873 sub_sm<sm_impl<TSM>>::get(&subs).process_event(event, deps, subs);
878 struct transitions_sub<sm<TSM>> {
879 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
880 static bool execute(
const TEvent &event, SM &, TDeps &deps, TSubs &subs,
typename SM::state_t &) {
881 return sub_sm<sm_impl<TSM>>::get(&subs).template process_event<TEvent>(event, deps, subs);
895 struct transitions_sub;
896 template <
class,
class>
897 struct state_mappings;
898 template <
class S,
class... Ts>
899 struct state_mappings<S, aux::type_list<Ts...>> {
900 using element_type = state<S>;
901 using types = aux::type_list<Ts...>;
903 template <
class,
class>
904 struct event_mappings;
905 template <
class E,
class... Ts>
906 struct event_mappings<E, aux::inherit<Ts...>> {
907 using element_type = event<E>;
908 using types = aux::type_list<Ts...>;
911 struct unique_mappings;
912 template <
class,
class...>
913 struct unique_mappings_impl;
914 template <
class... Ts>
915 using unique_mappings_t =
typename unique_mappings<Ts...>
::type;
916 template <
class,
class,
class,
class R>
917 struct get_mapping : aux::type_list<R> {};
918 template <
class E,
class T,
class R>
919 struct get_mapping<event<E>, event<E>, T, R>
920 : aux::type_list<event_mappings<E, aux::apply_t<unique_mappings_t, aux::join_t<typename R::types, typename T::types>>>> {};
921 template <
class S,
class T,
class R>
922 struct get_mapping<state<S>, state<S>, T, R>
923 : aux::type_list<state_mappings<S, aux::join_t<typename R::types, typename T::types>>> {};
924 template <
class T,
class... Ts>
925 struct extend_mapping : aux::join_t<typename get_mapping<typename T::element_type, typename Ts::element_type, T, Ts>::type...> {
927 template <
class T,
class... Ts>
928 using extend_mapping_t = aux::apply_t<aux::inherit,
typename extend_mapping<T, Ts...>
::type>;
929 template <bool,
class,
class...>
930 struct conditional_mapping;
931 template <
class T1,
class T2,
class... Rs,
class... Ts>
932 struct conditional_mapping<true, aux::type<T1, aux::inherit<Rs...>>, T2, Ts...> {
933 using type = unique_mappings_impl<aux::type<aux::inherit<T1>, extend_mapping_t<T2, Rs...>>, Ts...>;
935 template <
class T1,
class T2,
class... Rs,
class... Ts>
936 struct conditional_mapping<false, aux::type<T1, aux::inherit<Rs...>>, T2, Ts...> {
938 unique_mappings_impl<aux::type<aux::inherit<T1, aux::type<typename T2::element_type>>, aux::inherit<T2, Rs...>>, Ts...>;
940 template <
class T1,
class T2,
class... Rs,
class... Ts>
941 struct unique_mappings_impl<aux::type<T1, aux::inherit<Rs...>>, T2, Ts...>
942 : conditional_mapping<aux::is_base_of<aux::type<typename T2::element_type>, T1>::value, aux::type<T1, aux::inherit<Rs...>>,
944 template <
class T1,
class Rs>
945 struct unique_mappings_impl<aux::type<T1, Rs>> : aux::apply_t<aux::inherit, Rs> {};
946 template <
class... Ts>
947 struct unique_mappings : unique_mappings_impl<aux::type<aux::none_type, aux::inherit<>>, Ts...> {};
949 struct unique_mappings<T> : aux::inherit<T> {};
950 template <
class,
class...>
952 template <
class... Ts>
953 struct mappings<aux::pool<Ts...>>
955 event_mappings<typename Ts::event, aux::inherit<state_mappings<typename Ts::src_state, aux::type_list<Ts>>>>...> {};
958 template <
class,
class TUnexpected>
959 transitions<TUnexpected> get_state_mapping_impl(...);
960 template <
class T,
class,
class... Ts>
961 transitions<Ts...> get_state_mapping_impl(state_mappings<T, aux::type_list<Ts...>> *);
962 template <
class T,
class TMappings,
class TUnexpected>
963 struct get_state_mapping {
964 using type = decltype(get_state_mapping_impl<T, TUnexpected>((TMappings *)0));
967 transitions_sub<S> get_sub_state_mapping_impl(...);
968 template <
class T,
class... Ts>
969 transitions_sub<T, Ts...> get_sub_state_mapping_impl(state_mappings<T, aux::type_list<Ts...>> *);
970 template <
class T,
class TMappings,
class TUnexpected>
971 struct get_state_mapping<sm<T>, TMappings, TUnexpected> {
972 using type = decltype(get_sub_state_mapping_impl<sm<T>>((TMappings *)0));
974 template <
class T,
class TMappings,
class TUnexpected>
977 transitions<aux::true_type> get_event_mapping_impl(...);
978 template <
class T,
class TMappings>
979 TMappings get_event_mapping_impl(event_mappings<T, TMappings> *);
980 template <
class T,
class... T1Mappings,
class... T2Mappings>
981 unique_mappings_t<T1Mappings..., T2Mappings...> get_event_mapping_impl(event_mappings<T, aux::inherit<T1Mappings...>> *,
982 event_mappings<_, aux::inherit<T2Mappings...>> *);
983 template <
class T,
class TMappings>
984 struct get_event_mapping_impl_helper
985 : aux::conditional<aux::is_same<transitions<aux::true_type>, decltype(get_event_mapping_impl<_>((TMappings *)0))>::value,
986 decltype(get_event_mapping_impl<T>((TMappings *)0)),
987 decltype(get_event_mapping_impl<T>((TMappings *)0, (TMappings *)0))>
::type {};
988 template <
class T,
class TMappings>
989 struct get_event_mapping_impl_helper<exception<T>, TMappings> : decltype(get_event_mapping_impl<exception<T>>((TMappings *)0)) {
991 template <
class T1,
class T2,
class TMappings>
992 struct get_event_mapping_impl_helper<unexpected_event<T1, T2>, TMappings>
993 : decltype(get_event_mapping_impl<unexpected_event<T1, T2>>((TMappings *)0)) {};
994 template <
class T1,
class T2,
class TMappings>
995 struct get_event_mapping_impl_helper<on_entry<T1, T2>, TMappings>
996 : decltype(get_event_mapping_impl<on_entry<T1, T2>>((TMappings *)0)) {};
997 template <
class T1,
class T2,
class TMappings>
998 struct get_event_mapping_impl_helper<on_exit<T1, T2>, TMappings>
999 : decltype(get_event_mapping_impl<on_exit<T1, T2>>((TMappings *)0)) {};
1000 template <
class T,
class TMappings>
1001 using get_event_mapping_t = get_event_mapping_impl_helper<T, TMappings>;
1004 namespace policies {
1005 struct dispatch_policy__ {};
1007 struct dispatch : aux::pair<dispatch_policy__, T> {
1011 template <
int,
class TMappings,
class sm_impl,
class State,
class TEvent,
class TDeps,
class TSubs>
1012 static bool dispatch(sm_impl &, State &,
const TEvent &, TDeps &, TSubs &,
const aux::type_list<> &) {
1015 template <int,
class TMappings,
class sm_impl,
class State,
class TEvent,
class TDeps,
class TSubs,
class... TStates>
1016 static bool dispatch(sm_impl &
self, State ¤t_state,
const TEvent &event, TDeps &deps, TSubs &subs,
1017 const aux::type_list<TStates...> &) {
1018 using dispatch_table_t = bool (*)(
const TEvent &, sm_impl &, TDeps &, TSubs &, State &);
1019 constexpr
static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(
sizeof...(TStates))] = {
1020 &get_state_mapping_t<TStates, TMappings, typename sm_impl::has_unexpected_events>::template execute<TEvent, sm_impl,
1022 return dispatch_table[current_state](event,
self, deps, subs, current_state);
1026 template <
int,
class TMappings,
class sm_impl,
class State,
class TEvent,
class TDeps,
class TSubs>
1027 static bool dispatch(sm_impl &, State &,
const TEvent &, TDeps &, TSubs &,
const aux::type_list<> &) {
1030 template <
int N,
class TMappings,
class sm_impl,
class State,
class TEvent,
class TDeps,
class TSubs,
class TState,
1032 static bool dispatch(sm_impl &
self, State ¤t_state,
const TEvent &event, TDeps &deps, TSubs &subs,
1033 const aux::type_list<TState, TStates...> &) {
1034 return current_state == N
1035 ? get_state_mapping_t<TState, TMappings, typename sm_impl::has_unexpected_events>::template execute<
1036 TEvent, sm_impl, TDeps, TSubs>(event,
self, deps, subs, current_state)
1037 : dispatch<N + 1, TMappings>(
self, current_state, event, deps, subs, aux::type_list<TStates...>{});
1041 template <
int,
class TMappings,
class sm_impl,
class State,
class TEvent,
class TDeps,
class TSubs>
1042 static bool dispatch(sm_impl &, State &,
const TEvent &, TDeps &, TSubs &,
const aux::type_list<> &) {
1045 template <
int N,
class TMappings,
class sm_impl,
class State,
class TEvent,
class TDeps,
class TSubs,
class TState,
1047 static bool dispatch(sm_impl &
self, State ¤t_state,
const TEvent &event, TDeps &deps, TSubs &subs,
1048 const aux::type_list<TState, TStates...> &) {
1049 switch (current_state) {
1051 return get_state_mapping_t<TState, TMappings, typename sm_impl::has_unexpected_events>::template execute<
1052 TEvent, sm_impl, TDeps, TSubs>(event,
self, deps, subs, current_state);
1054 return dispatch<N + 1, TMappings>(
self, current_state, event, deps, subs, aux::type_list<TStates...>{});
1058 #if defined(__cpp_fold_expressions) 1060 template <
class TMappings,
int... Ns,
class sm_impl,
class State,
class TEvent,
class TDeps,
class TSubs,
class... TStates>
1061 static bool dispatch_impl(sm_impl &
self, State ¤t_state, aux::index_sequence<Ns...>,
const TEvent &event, TDeps &deps,
1062 TSubs &subs,
const aux::type_list<TStates...> &) {
1063 return ((current_state == Ns
1064 ? get_state_mapping_t<TStates, TMappings, typename sm_impl::has_unexpected_events>::template execute<
1065 TEvent, sm_impl, TDeps, TSubs>(event,
self, deps, subs, current_state)
1069 template <
int N,
class TMappings,
class sm_impl,
class State,
class TEvent,
class TDeps,
class TSubs,
class... TStates>
1070 static bool dispatch(sm_impl &
self, State ¤t_state,
const TEvent &event, TDeps &deps, TSubs &subs,
1071 const aux::type_list<TStates...> &states) {
1072 return dispatch_impl<TMappings>(
self, current_state, aux::make_index_sequence<
sizeof...(TStates)>{}, event, deps, subs,
1082 template <
class,
class...>
1085 namespace policies {
1086 struct logger_policy__ {};
1088 struct logger : aux::pair<logger_policy__, logger<T>> {
1092 struct get_state_name;
1094 struct get_state_name<aux::string<T>> {
1095 using type = aux::string<T>;
1097 template <
class T,
class... Ts>
1098 struct get_state_name<aux::string<sm<sm_policy<T, Ts...>>>> {
1099 using type =
typename get_state_name<aux::string<sm_policy<T, Ts...>>>
::type;
1102 struct get_state_name<aux::string<sm_policy<T>>> {
1103 using type = aux::string<T>;
1105 template <
class T,
class TName>
1106 struct get_state_name<aux::string<sm_policy<T, TName>>> {
1107 using type = aux::string<T(typename TName::type)>;
1111 template <
class,
class TDeps,
class TEvent>
1112 void log_process_event(
const aux::type<no_policy> &, TDeps &,
const TEvent &) {}
1113 template <
class SM,
class TLogger,
class TDeps,
class TEvent>
1114 void log_process_event(
const aux::type<TLogger> &, TDeps &deps,
const TEvent &event) {
1115 return static_cast<aux::pool_type<TLogger &> &
>(deps).value.template log_process_event<SM>(event);
1117 template <
class,
class TDeps,
class TSrcState,
class TDstState>
1118 void log_state_change(
const aux::type<no_policy> &, TDeps &,
const TSrcState &,
const TDstState &) {}
1119 template <
class SM,
class TLogger,
class TDeps,
class TSrcState,
class TDstState>
1120 void log_state_change(
const aux::type<TLogger> &, TDeps &deps,
const TSrcState &,
const TDstState &) {
1121 return static_cast<aux::pool_type<TLogger &> &
>(deps).value.template log_state_change<SM>(get_state_name_t<TSrcState>{},
1122 get_state_name_t<TDstState>{});
1124 template <
class,
class TDeps,
class TAction,
class TEvent>
1125 void log_action(
const aux::type<no_policy> &, TDeps &,
const TAction &,
const TEvent &) {}
1126 template <
class SM,
class TLogger,
class TDeps,
class TAction,
class TEvent>
1127 void log_action(
const aux::type<TLogger> &, TDeps &deps,
const TAction &action,
const TEvent &event) {
1128 return static_cast<aux::pool_type<TLogger &> &
>(deps).value.template log_action<SM>(action, event);
1130 template <
class SM,
class TLogger,
class TDeps,
class TAction,
class TEvent>
1131 void log_action(
const aux::type<TLogger> &, TDeps &deps,
const aux::zero_wrapper<TAction> &action,
const TEvent &event) {
1132 return static_cast<aux::pool_type<TLogger &> &
>(deps).value.template log_action<SM>(action.get(), event);
1134 template <
class,
class TDeps,
class TGuard,
class TEvent>
1135 void log_guard(
const aux::type<no_policy> &, TDeps &,
const TGuard &,
const TEvent &,
bool) {}
1136 template <
class SM,
class TLogger,
class TDeps,
class TGuard,
class TEvent>
1137 void log_guard(
const aux::type<TLogger> &, TDeps &deps,
const TGuard &guard,
const TEvent &event,
bool result) {
1138 return static_cast<aux::pool_type<TLogger &> &
>(deps).value.template log_guard<SM>(guard, event, result);
1140 template <
class SM,
class TLogger,
class TDeps,
class TGuard,
class TEvent>
1141 void log_guard(
const aux::type<TLogger> &, TDeps &deps,
const aux::zero_wrapper<TGuard> &guard,
const TEvent &event,
1143 return static_cast<aux::pool_type<TLogger &> &
>(deps).value.template log_guard<SM>(guard.get(), event, result);
1148 namespace policies {
1149 struct process_queue_policy__ {};
1150 template <
template <
class...>
class T>
1151 struct process_queue : aux::pair<back::policies::process_queue_policy__, process_queue<T>> {
1153 using rebind = T<U>;
1158 namespace policies {
1159 struct testing_policy__ {};
1160 struct testing : aux::pair<testing_policy__, testing> {};
1164 namespace policies {
1165 struct thread_safety_policy__ {
1166 auto create_lock() {
return *
this; }
1167 __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
1169 template <
class TLock>
1170 struct thread_safe : aux::pair<thread_safety_policy__, thread_safe<TLock>> {
1171 using type = thread_safe;
1172 auto create_lock() {
1174 explicit lock_guard(TLock &lock) : lock_{lock} { lock_.lock(); }
1175 ~lock_guard() { lock_.unlock(); }
1178 return lock_guard{lock};
1185 struct no_policy : policies::thread_safety_policy__ {
1186 using type = no_policy;
1188 using rebind = no_policy;
1190 using defer = no_policy;
1191 using const_iterator = no_policy;
1192 using flag = no_policy;
1193 __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
1195 template <
class TDefault,
class>
1196 TDefault get_policy(...);
1197 template <
class,
class T,
class TPolicy>
1198 TPolicy get_policy(aux::pair<T, TPolicy> *);
1199 template <
class SM,
class... TPolicies>
1201 static_assert(aux::is_same<aux::remove_reference_t<SM>, SM>::value,
"SM type can't have qualifiers");
1202 #if defined(COMPILING_WITH_MSVC) 1203 using default_dispatch_policy = policies::jump_table;
1204 #elif defined(__clang__) 1205 using default_dispatch_policy = policies::jump_table;
1206 #elif defined(__GNUC__) 1207 using default_dispatch_policy = policies::branch_stm;
1210 using thread_safety_policy =
1211 decltype(get_policy<no_policy, policies::thread_safety_policy__>((aux::inherit<TPolicies...> *)0));
1212 using defer_queue_policy = decltype(get_policy<no_policy, policies::defer_queue_policy__>((aux::inherit<TPolicies...> *)0));
1213 using process_queue_policy =
1214 decltype(get_policy<no_policy, policies::process_queue_policy__>((aux::inherit<TPolicies...> *)0));
1215 using logger_policy = decltype(get_policy<no_policy, policies::logger_policy__>((aux::inherit<TPolicies...> *)0));
1216 using testing_policy = decltype(get_policy<no_policy, policies::testing_policy__>((aux::inherit<TPolicies...> *)0));
1217 using dispatch_policy =
1218 decltype(get_policy<default_dispatch_policy, policies::dispatch_policy__>((aux::inherit<TPolicies...> *)0));
1220 using rebind =
typename rebind_impl<T, TPolicies...>
::type;
1223 namespace concepts {
1224 struct callable_fallback {
1228 aux::false_type test_callable(aux::non_type<
void (callable_fallback::*)(), &T::operator()> *);
1230 aux::true_type test_callable(...);
1231 template <
class,
class T>
1233 : decltype(test_callable<aux::inherit<aux::conditional_t<__is_class(T), T, aux::none_type>, callable_fallback>>(0)) {};
1235 namespace concepts {
1237 decltype(aux::declval<T>().
operator()()) composable_impl(
int);
1239 void composable_impl(...);
1241 struct composable : aux::is<aux::pool, decltype(composable_impl<T>(0))> {};
1243 #if !defined(BOOST_SML_DISABLE_EXCEPTIONS) 1244 #if !(defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) 1245 #define BOOST_SML_DISABLE_EXCEPTIONS true 1247 #define BOOST_SML_DISABLE_EXCEPTIONS false 1251 template <
class TSM>
1252 struct sm_impl : aux::conditional_t<aux::is_empty<typename TSM::sm>::value, aux::none_type, typename TSM::sm> {
1253 using sm_t =
typename TSM::sm;
1256 using defer_queue_t =
typename TSM::defer_queue_policy::template rebind<T>;
1257 using defer_flag_t =
typename TSM::defer_queue_policy::flag;
1259 using process_queue_t =
typename TSM::process_queue_policy::template rebind<T>;
1261 using dispatch_t =
typename TSM::dispatch_policy;
1262 using transitions_t = decltype(aux::declval<sm_t>().
operator()());
1263 using states_t = aux::apply_t<aux::unique_t, aux::apply_t<get_states, transitions_t>>;
1264 using states_ids_t = aux::apply_t<aux::type_id, states_t>;
1265 using initial_states_t = aux::apply_t<aux::unique_t, aux::apply_t<get_initial_states, transitions_t>>;
1266 using initial_states_ids_t = aux::apply_t<aux::type_id, initial_states_t>;
1267 using history_states_t = aux::apply_t<get_history_states, transitions_t>;
1268 using has_history_states =
1269 aux::integral_constant<bool, aux::size<initial_states_t>::value != aux::size<history_states_t>::value>;
1270 using sub_internal_events_t = aux::apply_t<get_sub_internal_events, transitions_t>;
1271 using events_t = aux::apply_t<aux::unique_t, aux::join_t<sub_internal_events_t, aux::apply_t<get_all_events, transitions_t>>>;
1272 using events_ids_t = aux::apply_t<aux::inherit, events_t>;
1273 using has_unexpected_events =
typename aux::is_base_of<unexpected, aux::apply_t<aux::inherit, events_t>>
::type;
1274 using has_entry_exits =
typename aux::is_base_of<entry_exit, aux::apply_t<aux::inherit, events_t>>
::type;
1275 using defer_t = defer_queue_t<aux::apply_t<queue_event, events_t>>;
1276 using process_t = process_queue_t<aux::apply_t<queue_event, events_t>>;
1277 using deps = aux::apply_t<merge_deps, transitions_t>;
1278 using state_t = aux::conditional_t<(aux::size<states_t>::value > 0xFF),
unsigned short, aux::byte>;
1279 static constexpr
auto regions = aux::size<initial_states_t>::value;
1280 static_assert(regions > 0,
"At least one initial state is required");
1281 #if !BOOST_SML_DISABLE_EXCEPTIONS 1282 using exceptions = aux::apply_t<aux::unique_t, aux::apply_t<get_exceptions, events_t>>;
1283 using has_exceptions = aux::integral_constant<bool, (aux::size<exceptions>::value > 0)>;
1285 struct mappings : mappings_t<transitions_t> {};
1286 template <
class TPool>
1287 sm_impl(aux::init,
const TPool &p) : sm_impl{p, aux::is_empty<sm_t>{}} {}
1288 template <
class TPool>
1289 sm_impl(
const TPool &p, aux::false_type) : sm_t{aux::try_get<sm_t>(&p)}, transitions_{(*this)()} {
1290 initialize(
typename sm_impl<TSM>::initial_states_t{});
1292 template <
class TPool>
1293 sm_impl(
const TPool &p, aux::true_type) : transitions_{aux::try_get<sm_t>(&p)()} {
1294 initialize(
typename sm_impl<TSM>::initial_states_t{});
1296 template <
class TEvent,
class TDeps,
class TSubs>
1297 bool process_event(
const TEvent &event, TDeps &deps, TSubs &subs) {
1298 policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1299 #if BOOST_SML_DISABLE_EXCEPTIONS 1300 const auto handled = process_event_impl<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(
1301 event, deps, subs, states_t{}, aux::make_index_sequence<regions>{});
1303 const auto handled =
1304 process_event_noexcept<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, has_exceptions{});
1307 while (process_internal_events(anonymous{}, deps, subs)) {
1309 process_defer_events(deps, subs, handled,
aux::type<defer_queue_t<TEvent>>{}, events_t{});
1310 }
while (process_queued_events(deps, subs,
aux::type<process_queue_t<TEvent>>{}, events_t{}) ||
1311 process_internal_events(anonymous{}, deps, subs));
1314 void initialize(
const aux::type_list<> &) {}
1315 template <
class TState>
1316 void initialize(
const aux::type_list<TState> &) {
1317 current_state_[0] = aux::get_id<state_t, TState>((states_ids_t *)0);
1319 template <
class... TStates>
1320 void initialize(
const aux::type_list<TStates...> &) {
1322 #if defined(__cpp_fold_expressions) 1323 ((current_state_[region++] = aux::get_id<state_t, TStates>((states_ids_t *)0)), ...);
1325 (void)aux::swallow{0, (current_state_[region++] = aux::get_id<state_t, TStates>((states_ids_t *)0), 0)...};
1328 template <
class TDeps,
class TSubs>
1329 void start(TDeps &deps, TSubs &subs) {
1330 process_internal_events(on_entry<_, initial>{}, deps, subs);
1332 while (process_internal_events(anonymous{}, deps, subs)) {
1334 process_defer_events(deps, subs,
true,
aux::type<defer_queue_t<initial>>{}, events_t{});
1335 }
while (process_queued_events(deps, subs,
aux::type<process_queue_t<initial>>{}, events_t{}) ||
1336 process_internal_events(anonymous{}, deps, subs));
1338 template <
class TEvent,
class TDeps,
class TSubs,
class... Ts,
1339 __BOOST_SML_REQUIRES(!aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value &&
1340 !aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1341 bool process_internal_events(
const TEvent &, TDeps &, TSubs &, Ts &&...) {
1344 template <
class TEvent,
class TDeps,
class TSubs,
1345 __BOOST_SML_REQUIRES(aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value &&
1346 !aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1347 bool process_internal_events(
const TEvent &event, TDeps &deps, TSubs &subs) {
1348 policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1349 #if BOOST_SML_DISABLE_EXCEPTIONS 1350 return process_event_impl<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, states_t{},
1351 aux::make_index_sequence<regions>{});
1353 return process_event_noexcept<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, has_exceptions{});
1356 template <
class TEvent,
class TDeps,
class TSubs,
1357 __BOOST_SML_REQUIRES(aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1358 bool process_internal_events(
const TEvent &event, TDeps &deps, TSubs &subs) {
1359 policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1360 #if BOOST_SML_DISABLE_EXCEPTIONS 1361 return process_event_impl<get_event_mapping_t<get_mapped_t<TEvent>, mappings>>(event, deps, subs, states_t{},
1362 aux::make_index_sequence<regions>{});
1364 return process_event_noexcept<get_event_mapping_t<get_mapped_t<TEvent>, mappings>>(event, deps, subs, has_exceptions{});
1367 template <
class TEvent,
class TDeps,
class TSubs,
class... Ts,
1368 __BOOST_SML_REQUIRES(!aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value &&
1369 !aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1370 bool process_internal_event(
const TEvent &, TDeps &, TSubs &, Ts &&...) {
1373 template <
class TEvent,
class TDeps,
class TSubs,
1374 __BOOST_SML_REQUIRES(!aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value)>
1375 bool process_internal_generic_event(
const TEvent &, TDeps &, TSubs &, state_t &) {
1378 template <
class TEvent,
class TDeps,
class TSubs,
1379 __BOOST_SML_REQUIRES(aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value)>
1380 bool process_internal_generic_event(
const TEvent &event, TDeps &deps, TSubs &subs, state_t ¤t_state) {
1381 policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1382 #if BOOST_SML_DISABLE_EXCEPTIONS 1383 return process_event_impl<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, states_t{},
1386 return process_event_noexcept<get_event_mapping_t<get_generic_t<TEvent>, mappings>>(event, deps, subs, current_state,
1390 template <
class TEvent,
class TDeps,
class TSubs,
1391 __BOOST_SML_REQUIRES(aux::is_base_of<get_generic_t<TEvent>, events_ids_t>::value &&
1392 !aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1393 bool process_internal_event(
const TEvent &event, TDeps &deps, TSubs &subs, state_t ¤t_state) {
1394 return process_internal_generic_event(event, deps, subs, current_state);
1396 template <
class TEvent,
class TDeps,
class TSubs,
1397 __BOOST_SML_REQUIRES(aux::is_base_of<get_mapped_t<TEvent>, events_ids_t>::value)>
1398 bool process_internal_event(
const TEvent &event, TDeps &deps, TSubs &subs, state_t ¤t_state) {
1399 policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1400 #if BOOST_SML_DISABLE_EXCEPTIONS 1401 return process_event_impl<get_event_mapping_t<get_mapped_t<TEvent>, mappings>>(event, deps, subs, states_t{}, current_state)
1403 return process_event_noexcept<get_event_mapping_t<get_mapped_t<TEvent>, mappings>>(event, deps, subs, current_state,
1406 || process_internal_generic_event(event, deps, subs, current_state);
1408 template <
class TMappings,
class TEvent,
class TDeps,
class TSubs,
class... TStates>
1409 bool process_event_impl(
const TEvent &event, TDeps &deps, TSubs &subs,
const aux::type_list<TStates...> &states,
1410 aux::index_sequence<0>) {
1411 const auto lock = thread_safety_.create_lock();
1413 return dispatch_t::template dispatch<0, TMappings>(*
this, current_state_[0], event, deps, subs, states);
1415 template <
class TMappings,
class TEvent,
class TDeps,
class TSubs,
class... TStates,
int... Ns>
1416 bool process_event_impl(
const TEvent &event, TDeps &deps, TSubs &subs,
const aux::type_list<TStates...> &states,
1417 aux::index_sequence<Ns...>) {
1418 const auto lock = thread_safety_.create_lock();
1420 #if defined(__cpp_fold_expressions) 1421 return ((dispatch_t::template dispatch<0, TMappings>(*
this, current_state_[Ns], event, deps, subs, states)), ...);
1423 auto handled =
false;
1426 (handled |= dispatch_t::template dispatch<0, TMappings>(*
this, current_state_[Ns], event, deps, subs, states), 0)...};
1430 template <
class TMappings,
class TEvent,
class TDeps,
class TSubs,
class... TStates>
1431 bool process_event_impl(
const TEvent &event, TDeps &deps, TSubs &subs,
const aux::type_list<TStates...> &states,
1432 state_t ¤t_state) {
1433 const auto lock = thread_safety_.create_lock();
1435 return dispatch_t::template dispatch<0, TMappings>(*
this, current_state, event, deps, subs, states);
1437 #if !BOOST_SML_DISABLE_EXCEPTIONS 1438 template <
class TMappings,
class TEvent,
class TDeps,
class TSubs>
1439 bool process_event_noexcept(
const TEvent &event, TDeps &deps, TSubs &subs, aux::false_type) noexcept {
1440 return process_event_impl<TMappings>(event, deps, subs, states_t{}, aux::make_index_sequence<regions>{});
1442 template <
class TMappings,
class TEvent,
class TDeps,
class TSubs>
1443 bool process_event_noexcept(
const TEvent &event, TDeps &deps, TSubs &subs, state_t ¤t_state, aux::false_type) noexcept {
1444 return process_event_impl<TMappings>(event, deps, subs, states_t{}, current_state);
1446 template <
class TMappings,
class TEvent,
class TDeps,
class TSubs>
1447 bool process_event_noexcept(
const TEvent &event, TDeps &deps, TSubs &subs, state_t ¤t_state, aux::true_type) noexcept {
1449 return process_event_impl<TMappings>(event, deps, subs, states_t{}, current_state);
1451 return process_exception(deps, subs, exceptions{});
1454 template <
class TMappings,
class TEvent,
class TDeps,
class TSubs>
1455 bool process_event_noexcept(
const TEvent &event, TDeps &deps, TSubs &subs, aux::true_type) {
1457 return process_event_impl<TMappings>(event, deps, subs, states_t{}, aux::make_index_sequence<regions>{});
1459 return process_exception(deps, subs, exceptions{});
1462 template <
class TDeps,
class TSubs>
1463 bool process_exception(TDeps &deps, TSubs &subs,
const aux::type_list<> &) {
1464 return process_internal_events(exception<_>{}, deps, subs);
1466 template <
class TDeps,
class TSubs,
class E,
class... Es>
1467 bool process_exception(TDeps &deps, TSubs &subs,
const aux::type_list<E, Es...> &) {
1470 }
catch (
const typename E::type &e) {
1471 return process_internal_events(E{e}, deps, subs);
1473 return process_exception(deps, subs, aux::type_list<Es...>{});
1477 template <
class TDeps,
class TSubs,
class... TEvents>
1478 bool process_defer_events(TDeps &, TSubs &,
const bool,
const aux::type<no_policy> &,
const aux::type_list<TEvents...> &) {
1481 template <
class TDeps,
class TSubs,
class TEvent>
1482 bool process_event_no_defer(TDeps &deps, TSubs &subs,
const void *data) {
1483 const auto &
event = *
static_cast<const TEvent *
>(data);
1484 policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1485 #if BOOST_SML_DISABLE_EXCEPTIONS 1486 const auto handled = process_event_impl<get_event_mapping_t<TEvent, mappings>>(event, deps, subs, states_t{},
1487 aux::make_index_sequence<regions>{});
1489 const auto handled = process_event_noexcept<get_event_mapping_t<TEvent, mappings>>(event, deps, subs, has_exceptions{});
1491 if (handled && defer_again_) {
1494 defer_.erase(defer_it_);
1495 defer_it_ = defer_.begin();
1496 defer_end_ = defer_.end();
1500 template <
class TDeps,
class TSubs,
class TDeferQueue,
class... TEvents>
1501 bool process_defer_events(TDeps &deps, TSubs &subs,
const bool handled,
const aux::type<TDeferQueue> &,
1502 const aux::type_list<TEvents...> &) {
1503 bool processed_events =
false;
1505 using dispatch_table_t = bool (sm_impl::*)(TDeps &, TSubs &,
const void *);
1506 const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(
sizeof...(TEvents))] = {
1507 &sm_impl::process_event_no_defer<TDeps, TSubs, TEvents>...};
1508 defer_processing_ =
true;
1509 defer_again_ =
false;
1510 defer_it_ = defer_.begin();
1511 defer_end_ = defer_.end();
1512 processed_events = defer_it_ != defer_end_;
1513 while (defer_it_ != defer_end_) {
1514 (this->*dispatch_table[defer_it_->id])(deps, subs, defer_it_->data);
1515 defer_again_ =
false;
1517 defer_processing_ =
false;
1519 return processed_events;
1521 template <
class TDeps,
class TSubs,
class... TEvents>
1522 bool process_queued_events(TDeps &, TSubs &,
const aux::type<no_policy> &,
const aux::type_list<TEvents...> &) {
1525 template <
class TDeps,
class TSubs,
class TEvent>
1526 bool process_event_no_queue(TDeps &deps, TSubs &subs,
const void *data) {
1527 const auto &
event = *
static_cast<const TEvent *
>(data);
1528 policies::log_process_event<sm_t>(aux::type<logger_t>{}, deps, event);
1529 #if BOOST_SML_DISABLE_EXCEPTIONS 1530 return process_event_impl<get_event_mapping_t<TEvent, mappings>>(event, deps, subs, states_t{},
1531 aux::make_index_sequence<regions>{});
1533 return process_event_noexcept<get_event_mapping_t<TEvent, mappings>>(event, deps, subs, has_exceptions{});
1536 template <
class TDeps,
class TSubs,
class TDeferQueue,
class... TEvents>
1537 bool process_queued_events(TDeps &deps, TSubs &subs,
const aux::type<TDeferQueue> &,
const aux::type_list<TEvents...> &) {
1538 using dispatch_table_t = bool (sm_impl::*)(TDeps &, TSubs &,
const void *);
1539 const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(
sizeof...(TEvents))] = {
1540 &sm_impl::process_event_no_queue<TDeps, TSubs, TEvents>...};
1541 bool wasnt_empty = !process_.empty();
1542 while (!process_.empty()) {
1543 (this->*dispatch_table[process_.front().id])(deps, subs, process_.front().data);
1548 template <
class TVisitor,
class... TStates>
1549 void visit_current_states(
const TVisitor &visitor,
const aux::type_list<TStates...> &, aux::index_sequence<0>)
const {
1550 using dispatch_table_t = void (*)(
const TVisitor &);
1551 const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(
sizeof...(TStates))] = {
1552 &sm_impl::visit_state<TVisitor, TStates>...};
1553 dispatch_table[current_state_[0]](visitor);
1555 template <
class TVisitor,
class... TStates,
int... Ns>
1556 void visit_current_states(
const TVisitor &visitor,
const aux::type_list<TStates...> &, aux::index_sequence<Ns...>)
const {
1557 using dispatch_table_t = void (*)(
const TVisitor &);
1558 const static dispatch_table_t dispatch_table[__BOOST_SML_ZERO_SIZE_ARRAY_CREATE(
sizeof...(TStates))] = {
1559 &sm_impl::visit_state<TVisitor, TStates>...};
1560 #if defined(__cpp_fold_expressions) 1561 (dispatch_table[current_state_[Ns]](visitor), ...);
1563 (void)aux::swallow{0, (dispatch_table[current_state_[Ns]](visitor), 0)...};
1566 template <
class TVisitor,
class TState>
1567 static void visit_state(
const TVisitor &visitor) {
1568 visitor(aux::string<TState>{});
1570 bool is_terminated()
const {
return is_terminated_impl(aux::make_index_sequence<regions>{}); }
1571 bool is_terminated_impl(aux::index_sequence<0>)
const {
1572 return current_state_[0] == aux::get_id<state_t, terminate_state>((states_ids_t *)0);
1574 template <
int... Ns>
1575 bool is_terminated_impl(aux::index_sequence<Ns...>)
const {
1576 #if defined(__cpp_fold_expressions) 1577 return ((current_state_[Ns] == aux::get_id<state_t, terminate_state>((states_ids_t *)0)) && ...);
1581 0, (current_state_[Ns] == aux::get_id<state_t, terminate_state>((states_ids_t *)0) ? result : (result =
false))...};
1585 transitions_t transitions_;
1586 state_t current_state_[regions];
1587 thread_safety_t thread_safety_;
1590 defer_flag_t defer_processing_ = defer_flag_t{};
1591 defer_flag_t defer_again_ = defer_flag_t{};
1592 typename defer_t::const_iterator defer_it_;
1593 typename defer_t::const_iterator defer_end_;
1595 template <
class TSM>
1597 using sm_t =
typename TSM::sm;
1599 using logger_dep_t =
1600 aux::conditional_t<aux::is_same<no_policy, logger_t>::value, aux::type_list<>, aux::type_list<logger_t &>>;
1601 using transitions_t = decltype(aux::declval<sm_t>().
operator()());
1602 static_assert(concepts::composable<sm_t>::value,
"Composable constraint is not satisfied!");
1605 using states = aux::apply_t<aux::unique_t, aux::apply_t<get_states, transitions_t>>;
1606 using state_machines = aux::apply_t<get_sub_sms, states>;
1607 using events = aux::apply_t<aux::unique_t, aux::apply_t<get_all_events, transitions_t>>;
1608 using transitions = aux::apply_t<aux::type_list, transitions_t>;
1611 using sm_all_t = aux::apply_t<get_non_empty_t, aux::join_t<aux::type_list<sm_t>, aux::apply_t<get_sm_t, state_machines>>>;
1613 aux::apply_t<aux::pool,
1614 typename convert_to_sm<TSM, aux::apply_t<aux::unique_t, aux::apply_t<get_sub_sms, states>>>::type>;
1615 using deps = aux::apply_t<merge_deps, transitions_t>;
1617 aux::apply_t<aux::pool,
1618 aux::apply_t<aux::unique_t, aux::join_t<deps, sm_all_t, logger_dep_t, aux::apply_t<merge_deps, sub_sms_t>>>>;
1619 struct events_ids : aux::apply_t<aux::inherit, events> {};
1622 sm() : deps_{aux::init{}, aux::pool<>{}}, sub_sms_{aux::pool<>{}} { aux::get<sm_impl<TSM>>(sub_sms_).start(deps_, sub_sms_); }
1623 template <
class TDeps, __BOOST_SML_REQUIRES(!aux::is_same<aux::remove_reference_t<TDeps>, sm>::value)>
1624 explicit sm(TDeps &&deps) : deps_{aux::init{}, aux::pool<TDeps>{deps}}, sub_sms_{aux::pool<TDeps>{deps}} {
1625 aux::get<sm_impl<TSM>>(sub_sms_).start(deps_, sub_sms_);
1627 template <
class... TDeps, __BOOST_SML_REQUIRES((
sizeof...(TDeps) > 1) && aux::is_unique_t<TDeps...>::value)>
1628 explicit sm(TDeps &&... deps) : deps_{aux::init{}, aux::pool<TDeps...>{deps...}}, sub_sms_{aux::pool<TDeps...>{deps...}} {
1629 aux::get<sm_impl<TSM>>(sub_sms_).start(deps_, sub_sms_);
1631 sm(aux::init, deps_t &deps) : deps_{deps}, sub_sms_{deps} { aux::get<sm_impl<TSM>>(sub_sms_).start(deps_, sub_sms_); }
1632 sm(
const sm &) =
default;
1633 sm(sm &&) =
default;
1634 sm &operator=(
const sm &) =
default;
1635 sm &operator=(sm &&) =
default;
1636 template <class TEvent, __BOOST_SML_REQUIRES(aux::is_base_of<TEvent, events_ids>::value)>
1637 bool process_event(
const TEvent &event) {
1638 return aux::get<sm_impl<TSM>>(sub_sms_).process_event(event, deps_, sub_sms_);
1640 template <class TEvent, __BOOST_SML_REQUIRES(!aux::is_base_of<TEvent, events_ids>::value)>
1641 bool process_event(
const TEvent &event) {
1642 return aux::get<sm_impl<TSM>>(sub_sms_).process_event(unexpected_event<_, TEvent>{
event}, deps_, sub_sms_);
1644 template <
class T = aux::
identity<sm_t>,
class TVisitor, __BOOST_SML_REQUIRES(concepts::callable<
void, TVisitor>::value)>
1645 void visit_current_states(
const TVisitor &visitor)
const {
1646 using type =
typename T::type;
1647 using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1648 using states_t =
typename sm_impl_t::states_t;
1649 constexpr
auto regions = sm_impl_t::regions;
1650 aux::cget<sm_impl_t>(sub_sms_).visit_current_states(visitor, states_t{}, aux::make_index_sequence<regions>{});
1652 template <
class T = aux::
identity<sm_t>,
class TState>
1653 bool is(
const TState &)
const {
1654 using type =
typename T::type;
1655 using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1656 using state_t =
typename sm_impl_t::state_t;
1657 using states_ids_t =
typename sm_impl_t::states_ids_t;
1658 return aux::get_id<state_t, typename TState::type>((states_ids_t *)0) == aux::cget<sm_impl_t>(sub_sms_).current_state_[0];
1660 template <
class T = aux::
identity<sm_t>,
template <
class...>
class TState>
1661 bool is(
const TState<terminate_state> &)
const {
1662 using type =
typename T::type;
1663 using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1664 using state_t =
typename sm_impl_t::state_t;
1665 using states_ids_t =
typename sm_impl_t::states_ids_t;
1666 auto result =
false;
1667 visit_current_states<T>([&](
auto state) {
1669 result |= (aux::get_id<state_t, terminate_state>((states_ids_t *)0) ==
1670 aux::get_id<state_t, typename decltype(state)::type>((states_ids_t *)0));
1674 template <
class T = aux::
identity<sm_t>,
class... TStates,
1675 __BOOST_SML_REQUIRES(sizeof...(TStates) == sm_impl<
typename TSM::
template rebind<
typename T::type>>::regions)>
1676 bool is(
const TStates &...)
const {
1677 using type =
typename T::type;
1678 using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1679 using states_ids_t =
typename sm_impl_t::states_ids_t;
1680 using state_t =
typename sm_impl_t::state_t;
1683 state_t state_ids[] = {aux::get_id<state_t, typename TStates::type>((states_ids_t *)0)...};
1684 visit_current_states<T>([&](
auto state) {
1686 result &= (aux::get_id<state_t, typename decltype(state)::type>((states_ids_t *)0) == state_ids[i++]);
1690 template <
class T = aux::
identity<sm_t>,
class... TStates,
1691 __BOOST_SML_REQUIRES(!aux::is_same<no_policy,
typename TSM::testing_policy>::value && aux::always<T>::value)>
1692 void set_current_states(
const TStates &...) {
1693 using type =
typename T::type;
1694 using sm_impl_t = sm_impl<typename TSM::template rebind<type>>;
1695 using states_ids_t =
typename sm_impl_t::states_ids_t;
1696 using state_t =
typename sm_impl_t::state_t;
1697 auto &sm = aux::get<sm_impl_t>(sub_sms_);
1699 #if defined(__cpp_fold_expressions) 1700 ((sm.current_state_[region++] = aux::get_id<state_t, typename TStates::type>((states_ids_t *)0)), ...);
1702 (void)aux::swallow{0,
1703 (sm.current_state_[region++] = aux::get_id<state_t, typename TStates::type>((states_ids_t *)0), 0)...};
1708 return aux::get<sm_impl<typename TSM::template rebind<T>>>(sub_sms_);
1711 operator const T &() {
1712 return aux::cget<sm_impl<typename TSM::template rebind<T>>>(sub_sms_);
1721 struct operator_base {};
1722 struct action_base {};
1723 template <
class TRootSM,
class... TSubSMs>
1724 TRootSM get_root_sm_impl(aux::pool<TRootSM, TSubSMs...> *);
1725 template <
class TSubs>
1726 using get_root_sm_t = decltype(get_root_sm_impl((TSubs *)0));
1727 template <
class,
class>
1728 aux::type_list<action_base> args1__(...);
1729 template <
class T,
class E>
1730 auto args1__(
int) -> aux::function_traits_t<decltype(&T::operator())>;
1731 template <
class T,
class E>
1732 auto args__(
int) -> aux::function_traits_t<decltype(&T::__BOOST_SML_TEMPLATE_KEYWORD operator()<back::get_event_t<E>>)>;
1733 template <
class T,
class E>
1734 auto args__(...) -> decltype(args1__<T, E>(0));
1735 template <
class T,
class E>
1736 using args_t = decltype(args__<T, E>(0));
1737 template <
class T,
class TEvent,
class TSM,
class TDeps>
1738 decltype(
auto) get_arg(const aux::type<T> &, const TEvent &, TSM &, TDeps &deps) {
1739 return aux::get<T>(deps);
1741 template <
class TEvent,
class TSM,
class TDeps>
1742 decltype(
auto) get_arg(const aux::type<TEvent> &, const TEvent &event, TSM &, TDeps &) {
1745 template <
class TEvent,
class TSM,
class TDeps>
1746 decltype(
auto) get_arg(const aux::type<const TEvent &> &, const TEvent &event, TSM &, TDeps &) {
1749 template <
class T,
class TEvent,
class TSM,
class TDeps>
1750 decltype(
auto) get_arg(const aux::type<const TEvent &> &, const back::unexpected_event<T, TEvent> &event, TSM &, TDeps &) {
1751 return event.event_;
1753 template <
class T,
class TEvent,
class TSM,
class TDeps>
1754 decltype(
auto) get_arg(const aux::type<const TEvent &> &, const back::on_entry<T, TEvent> &event, TSM &, TDeps &) {
1755 return event.event_;
1757 template <
class T,
class TEvent,
class TSM,
class TDeps>
1758 decltype(
auto) get_arg(const aux::type<const TEvent &> &, const back::on_exit<T, TEvent> &event, TSM &, TDeps &) {
1759 return event.event_;
1761 template <
class T,
class TEvent,
class TSM,
class TDeps>
1762 decltype(
auto) get_arg(const aux::type<const TEvent &> &, const back::exception<T, TEvent> &event, TSM &, TDeps &) {
1763 return event.exception_;
1765 template <
class... TEvents,
class TEvent,
class TSM,
class TDeps>
1766 decltype(
auto) get_arg(const aux::type<back::defer<TEvents...>> &, const TEvent, TSM &sm, TDeps &) {
1767 return back::defer<TEvents...>{sm.defer_};
1769 template <
class... TEvents,
class TEvent,
class TSM,
class TDeps>
1770 decltype(
auto) get_arg(const aux::type<back::process<TEvents...>> &, const TEvent, TSM &sm, TDeps &) {
1771 return back::process<TEvents...>{sm.process_};
1773 template <
class,
class,
class>
1775 template <
class TEvent>
1776 struct call<TEvent, aux::type_list<>, back::no_policy> {
1777 template <
class T,
class TSM,
class TDeps,
class TSubs>
1778 static auto execute(T
object,
const TEvent &, TSM &, TDeps &, TSubs &) {
1782 template <
class TEvent,
class TLogger>
1783 struct call<TEvent, aux::type_list<>, TLogger> {
1784 template <
class T,
class TSM,
class TDeps,
class TSubs>
1785 static auto execute(T
object,
const TEvent &event, TSM &, TDeps &deps, TSubs &) {
1786 using result_type = decltype(
object());
1787 return execute_impl<typename TSM::sm_t>(aux::type<result_type>{}, object, event, deps);
1789 template <
class TSM,
class T,
class TDeps>
1790 static auto execute_impl(
const aux::type<bool> &, T
object,
const TEvent &event, TDeps &deps) {
1791 const auto result = object();
1792 back::policies::log_guard<TSM>(aux::type<TLogger>{}, deps, object, event, result);
1795 template <
class TSM,
class T,
class TDeps>
1796 static auto execute_impl(
const aux::type<void> &, T
object,
const TEvent &event, TDeps &deps) {
1797 back::policies::log_action<TSM>(aux::type<TLogger>{}, deps, object, event);
1801 template <
class TEvent>
1802 struct call<TEvent, aux::type_list<TEvent>, back::no_policy> {
1803 template <
class T,
class TSM,
class TDeps,
class TSubs>
1804 static auto execute(T
object,
const TEvent &event, TSM &, TDeps &, TSubs &) {
1805 return object(event);
1808 template <
class TEvent,
class TLogger>
1809 struct call<TEvent, aux::type_list<TEvent>, TLogger> {
1810 template <
class T,
class TSM,
class TDeps,
class TSubs>
1811 static auto execute(T
object,
const TEvent &event, TSM &, TDeps &deps, TSubs &) {
1812 using result_type = decltype(
object(event));
1813 return execute_impl<typename TSM::sm_t>(aux::type<result_type>{}, object, event, deps);
1815 template <
class TSM,
class T,
class TDeps>
1816 static auto execute_impl(
const aux::type<bool> &, T
object,
const TEvent &event, TDeps &deps) {
1817 const auto result = object(event);
1818 back::policies::log_guard<TSM>(aux::type<TLogger>{}, deps, object, event, result);
1821 template <
class TSM,
class T,
class TDeps>
1822 static auto execute_impl(
const aux::type<void> &, T
object,
const TEvent &event, TDeps &deps) {
1823 back::policies::log_action<TSM>(aux::type<TLogger>{}, deps, object, event);
1827 template <
class TEvent>
1828 struct call<TEvent, aux::type_list<action_base>, back::no_policy> {
1829 template <
class T,
class TSM,
class TDeps,
class TSubs>
1830 static auto execute(T
object,
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1831 return object(event, sm, deps, subs);
1834 template <
class TEvent,
class TLogger>
1835 struct call<TEvent, aux::type_list<action_base>, TLogger> {
1836 template <
class T,
class TSM,
class TDeps,
class TSubs>
1837 static auto execute(T
object,
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1838 return object(event, sm, deps, subs);
1841 template <
class TEvent,
class... Ts>
1842 struct call<TEvent, aux::type_list<Ts...>, back::no_policy> {
1843 template <
class T,
class TSM,
class TDeps,
class TSubs>
1844 static auto execute(T
object,
const TEvent &event, TSM &sm, TDeps &deps, TSubs &) {
1845 return object(get_arg(aux::type<Ts>{}, event, sm, deps)...);
1848 template <
class TEvent,
class... Ts,
class TLogger>
1849 struct call<TEvent, aux::type_list<Ts...>, TLogger> {
1850 template <
class T,
class TSM,
class TDeps,
class TSubs>
1851 static auto execute(T
object,
const TEvent &event, TSM &sm, TDeps &deps, TSubs &) {
1852 using result_type = decltype(
object(get_arg(aux::type<Ts>{}, event, sm, deps)...));
1853 return execute_impl<typename TSM::sm_t>(aux::type<result_type>{}, object, event, sm, deps);
1855 template <
class TSM,
class T,
class SM,
class TDeps>
1856 static auto execute_impl(
const aux::type<bool> &, T
object,
const TEvent &event, SM &sm, TDeps &deps) {
1857 const auto result = object(get_arg(aux::type<Ts>{}, event, sm, deps)...);
1858 back::policies::log_guard<TSM>(aux::type<TLogger>{}, deps, object, event, result);
1861 template <
class TSM,
class T,
class SM,
class TDeps>
1862 static auto execute_impl(
const aux::type<void> &, T
object,
const TEvent &event, SM &sm, TDeps &deps) {
1863 back::policies::log_action<TSM>(aux::type<TLogger>{}, deps, object, event);
1864 object(get_arg(aux::type<Ts>{}, event, sm, deps)...);
1867 template <
class... Ts>
1868 class seq_ : operator_base {
1870 explicit seq_(Ts... ts) : a(ts...) {}
1871 template <
class TEvent,
class TSM,
class TDeps,
class TSubs>
1872 void operator()(
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1873 for_all(aux::make_index_sequence<
sizeof...(Ts)>{}, event, sm, deps, subs);
1877 template <
int... Ns,
class TEvent,
class TSM,
class TDeps,
class TSubs>
1878 void for_all(
const aux::index_sequence<Ns...> &,
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1879 #if defined(__cpp_fold_expressions) 1880 (call<TEvent, args_t<Ts, TEvent>,
typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&a), event, sm, deps, subs), ...);
1883 0, (call<TEvent, args_t<Ts, TEvent>,
typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&a), event, sm, deps, subs),
1887 aux::tuple<Ts...> a;
1889 template <
class... Ts>
1890 class and_ : operator_base {
1892 explicit and_(Ts... ts) : g(ts...) {}
1893 template <
class TEvent,
class TSM,
class TDeps,
class TSubs>
1894 auto operator()(
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1895 return for_all(aux::make_index_sequence<
sizeof...(Ts)>{}, event, sm, deps, subs);
1899 template <
int... Ns,
class TEvent,
class TSM,
class TDeps,
class TSubs>
1900 auto for_all(
const aux::index_sequence<Ns...> &,
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1901 #if defined(__cpp_fold_expressions) 1902 return (call<TEvent, args_t<Ts, TEvent>,
typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&g), event, sm, deps, subs) &&
1906 (void)aux::swallow{0, (result && call<TEvent, args_t<Ts, TEvent>,
typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&g),
1907 event, sm, deps, subs)
1909 : (result =
false))...};
1913 aux::tuple<Ts...> g;
1915 template <
class... Ts>
1916 class or_ : operator_base {
1918 explicit or_(Ts... ts) : g(ts...) {}
1919 template <
class TEvent,
class TSM,
class TDeps,
class TSubs>
1920 auto operator()(
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1921 return for_all(aux::make_index_sequence<
sizeof...(Ts)>{}, event, sm, deps, subs);
1925 template <
int... Ns,
class TEvent,
class TSM,
class TDeps,
class TSubs>
1926 auto for_all(
const aux::index_sequence<Ns...> &,
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1927 #if defined(__cpp_fold_expressions) 1928 return (call<TEvent, args_t<Ts, TEvent>,
typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&g), event, sm, deps, subs) ||
1931 auto result =
false;
1932 (void)aux::swallow{0, (result || call<TEvent, args_t<Ts, TEvent>,
typename TSM::logger_t>::execute(aux::get_by_id<Ns>(&g),
1933 event, sm, deps, subs)
1939 aux::tuple<Ts...> g;
1942 class not_ : operator_base {
1944 explicit not_(T t) : g(t) {}
1945 template <
class TEvent,
class TSM,
class TDeps,
class TSubs>
1946 auto operator()(
const TEvent &event, TSM &sm, TDeps &deps, TSubs &subs) {
1947 return !call<TEvent, args_t<T, TEvent>,
typename TSM::logger_t>::execute(g, event, sm, deps, subs);
1954 template <class T, __BOOST_SML_REQUIRES(concepts::callable<bool, T>::value)>
1955 auto operator!(
const T &t) {
1956 return front::not_<aux::zero_wrapper<T>>(aux::zero_wrapper<T>{t});
1958 template <class T1, class T2, __BOOST_SML_REQUIRES(concepts::callable<bool, T1>::value &&concepts::callable<bool, T2>::value)>
1959 auto operator&&(
const T1 &t1,
const T2 &t2) {
1960 return front::and_<aux::zero_wrapper<T1>, aux::zero_wrapper<T2>>(aux::zero_wrapper<T1>{t1}, aux::zero_wrapper<T2>{t2});
1962 template <class T1, class T2, __BOOST_SML_REQUIRES(concepts::callable<bool, T1>::value &&concepts::callable<bool, T2>::value)>
1963 auto operator||(
const T1 &t1,
const T2 &t2) {
1964 return front::or_<aux::zero_wrapper<T1>, aux::zero_wrapper<T2>>(aux::zero_wrapper<T1>{t1}, aux::zero_wrapper<T2>{t2});
1966 template <class T1, class T2, __BOOST_SML_REQUIRES(concepts::callable<void, T1>::value &&concepts::callable<void, T2>::value)>
1967 auto operator,(
const T1 &t1,
const T2 &t2) {
1968 return front::seq_<aux::zero_wrapper<T1>, aux::zero_wrapper<T2>>(aux::zero_wrapper<T1>{t1}, aux::zero_wrapper<T2>{t2});
1972 struct defer : action_base {
1973 template <
class TEvent,
class TSM,
class TDeps,
class TSubs>
1974 void operator()(
const TEvent &event, TSM &sm, TDeps &, TSubs &) {
1975 if (sm.defer_processing_) {
1976 sm.defer_again_ =
true;
1978 sm.defer_.push_back(event);
1984 using testing = back::policies::testing;
1986 using logger = back::policies::logger<T>;
1988 using thread_safe = back::policies::thread_safe<T>;
1990 using dispatch = back::policies::dispatch<T>;
1991 template <
template <
class...>
class T>
1992 using defer_queue = back::policies::defer_queue<T>;
1993 template <
template <
class...>
class T>
1994 using process_queue = back::policies::process_queue<T>;
1995 #if defined(COMPILING_WITH_MSVC) 1996 template <
class T,
class... TPolicies,
class T__ = aux::remove_reference_t<decltype(aux::declval<T>())>>
1997 using sm = back::sm<back::sm_policy<T__, TPolicies...>>;
1999 template <
class T,
class... TPolicies>
2000 using sm = back::sm<back::sm_policy<T, TPolicies...>>;
2002 namespace concepts {
2003 aux::false_type transitional_impl(...);
2005 auto transitional_impl(T &&t) -> aux::always<
typename T::dst_state,
typename T::src_state,
typename T::event,
typename T::deps,
2006 decltype(T::initial), decltype(T::history)>;
2008 struct transitional : decltype(transitional_impl(aux::declval<T>())) {};
2013 template <
class TEvent>
2014 class process_impl :
public action_base {
2016 explicit process_impl(
const TEvent &event) : event(event) {}
2017 template <
class T,
class TSM,
class TDeps,
class TSubs>
2018 void operator()(
const T &, TSM &, TDeps &, TSubs &subs) {
2019 aux::get<get_root_sm_t<TSubs>>(subs).process_.push(event);
2025 template <
class TEvent>
2026 auto operator()(
const TEvent &event) {
2027 return process_impl<TEvent>{
event};
2033 template <
class,
class>
2034 struct transition_eg;
2035 template <
class,
class>
2036 struct transition_ea;
2037 template <
class TEvent>
2039 template <class T, __BOOST_SML_REQUIRES(concepts::callable<bool, T>::value)>
2040 auto operator[](
const T &t)
const {
2041 return transition_eg<event, aux::zero_wrapper<T>>{*
this, aux::zero_wrapper<T>{t}};
2043 template <class T, __BOOST_SML_REQUIRES(concepts::callable<void, T>::value)>
2044 auto operator/(
const T &t)
const {
2045 return transition_ea<event, aux::zero_wrapper<T>>{*
this, aux::zero_wrapper<T>{t}};
2047 auto operator()()
const {
return TEvent{}; }
2051 struct initial_state {};
2052 struct history_state {};
2055 template <
class,
class>
2056 struct transition_sa;
2057 template <
class,
class>
2058 struct transition_sg;
2059 template <
class,
class>
2060 struct transition_eg;
2063 template <
class TState>
2067 return transition<TState, T>{
static_cast<const TState &
>(*this), t};
2070 auto operator+(
const T &t)
const {
2071 return transition<TState, T>{
static_cast<const TState &
>(*this), t};
2073 template <class T, __BOOST_SML_REQUIRES(concepts::callable<bool, T>::value)>
2074 auto operator[](
const T &t)
const {
2075 return transition_sg<TState, aux::zero_wrapper<T>>{
static_cast<const TState &
>(*this), aux::zero_wrapper<T>{t}};
2077 template <class T, __BOOST_SML_REQUIRES(concepts::callable<void, T>::value)>
2078 auto operator/(
const T &t)
const {
2079 return transition_sa<TState, aux::zero_wrapper<T>>{
static_cast<const TState &
>(*this), aux::zero_wrapper<T>{t}};
2082 template <
class TState>
2083 struct state : state_impl<state<TState>> {
2084 using type = TState;
2085 static constexpr
auto initial =
false;
2086 static constexpr
auto history =
false;
2087 auto operator*()
const {
return state<TState(initial_state)>{}; }
2088 auto operator()(
const initial_state &)
const {
return state<TState(initial_state)>{}; }
2089 auto operator()(
const history_state &)
const {
return state<TState(history_state)>{}; }
2090 template <
class... Ts>
2091 auto operator()(
const state<Ts> &...)
const {
2092 return state<TState(Ts...)>{};
2095 auto operator=(
const T &t)
const {
2096 return transition<T, state>{t, *
this};
2100 return state<back::sm<back::sm_policy<T, aux::identity<TState>>>>{};
2103 template <
class TState>
2104 struct state<TState(initial_state)> : state_impl<state<TState(initial_state)>> {
2105 using type = TState;
2106 static constexpr
auto initial =
true;
2107 static constexpr
auto history =
false;
2109 auto operator=(
const T &t)
const {
2110 return transition<T, state>{t, *
this};
2113 template <
class TState>
2114 struct state<TState(history_state)> : state_impl<state<TState(history_state)>> {
2115 using type = TState;
2116 static constexpr
auto initial =
true;
2117 static constexpr
auto history =
true;
2119 auto operator=(
const T &t)
const {
2120 return transition<T, state>{t, *
this};
2123 #if defined(COMPILING_WITH_MSVC) 2124 template <
class T,
class T__ = aux::remove_reference_t<decltype(aux::declval<T>())>,
class =
void>
2126 using type = state<T>;
2128 template <
class T,
class T__>
2129 struct state_sm<T, T__, aux::enable_if_t<concepts::composable<T__>::value>> {
2130 using type = state<back::sm<back::sm_policy<T__>>>;
2133 template <
class T,
class =
void>
2135 using type = state<T>;
2138 struct state_sm<T, aux::enable_if_t<concepts::composable<T>::value>> {
2139 using type = state<back::sm<back::sm_policy<T>>>;
2145 template <
class,
class>
2147 template <
class E,
class... Ts>
2148 struct ignore<E, aux::type_list<Ts...>> {
2152 aux::conditional_t<aux::is_same<back::get_event_t<E>, aux::remove_const_t<aux::remove_reference_t<T>>>::value ||
2153 aux::is_same<T, action_base>::value,
2154 aux::type_list<>, aux::type_list<T>>;
2158 template <
class T,
class E,
class =
void>
2160 using type =
typename ignore<E, args_t<T, E>>
::type;
2162 template <
class T,
class E>
2164 template <
template <
class...>
class T,
class... Ts,
class E>
2165 struct get_deps<T<Ts...>, E, aux::enable_if_t<aux::is_base_of<operator_base, T<Ts...>>::value>> {
2166 using type = aux::join_t<get_deps_t<Ts, E>...>;
2169 using type = always;
2170 bool operator()()
const {
return true; }
2171 __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
2175 void operator()() {}
2176 __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
2180 template <
class E,
class G>
2181 struct transition<front::event<E>, G> {
2183 auto operator/(
const T &t)
const {
2184 return transition<front::event<E>, G, aux::zero_wrapper<T>>{e, g, aux::zero_wrapper<T>{t}};
2189 template <
class E,
class G,
class A>
2190 struct transition<front::event<E>, G, A> {
2195 template <
class S2,
class G,
class A>
2196 struct transition<state<S2>, G, A> : transition<state<internal>, state<S2>, front::event<back::anonymous>, G, A> {
2197 using transition<state<internal>, state<S2>, front::event<back::anonymous>, G, A>::g;
2198 using transition<state<internal>, state<S2>, front::event<back::anonymous>, G, A>::a;
2199 transition(
const G &g,
const A &a) : transition<state<internal>, state<S2>, front::event<back::anonymous>, G, A>{g, a} {}
2201 auto operator=(
const T &)
const {
2202 return transition<T, state<S2>, front::event<back::anonymous>, G, A>{g, a};
2205 template <
class S1,
class S2>
2206 struct transition<state<S1>, state<S2>> : transition<state<S1>, state<S2>, front::event<back::anonymous>, always, none> {
2207 transition(
const state<S1> &,
const state<S2> &)
2208 : transition<state<S1>, state<S2>, front::event<back::anonymous>, always, none>{always{}, none{}} {}
2210 template <
class S2,
class G>
2211 struct transition_sg<state<S2>, G> : transition<state<internal>, state<S2>, front::event<back::anonymous>, G, none> {
2212 using transition<state<internal>, state<S2>, front::event<back::anonymous>, G, none>::g;
2213 transition_sg(
const state<S2> &,
const G &g)
2214 : transition<state<internal>, state<S2>, front::event<back::anonymous>, G, none>{g, none{}} {}
2216 auto operator/(
const T &t)
const {
2217 return transition<state<S2>, G, aux::zero_wrapper<T>>{g, aux::zero_wrapper<T>{t}};
2220 auto operator=(
const T &)
const {
2221 return transition<T, state<S2>, front::event<back::anonymous>, G, none>{g, none{}};
2224 template <
class S2,
class A>
2225 struct transition_sa<state<S2>, A> : transition<state<internal>, state<S2>, front::event<back::anonymous>, always, A> {
2226 using transition<state<internal>, state<S2>, front::event<back::anonymous>, always, A>::a;
2227 transition_sa(
const state<S2> &,
const A &a)
2228 : transition<state<internal>, state<S2>, front::event<back::anonymous>, always, A>{always{}, a} {}
2230 auto operator=(
const T &)
const {
2231 return transition<T, state<S2>, front::event<back::anonymous>, always, A>{always{}, a};
2234 template <
class S2,
class E>
2235 struct transition<state<S2>, front::event<E>> {
2237 auto operator=(
const T &)
const {
2238 return transition<T, state<S2>, front::event<E>, always, none>{always{}, none{}};
2240 const state<S2> &s2;
2243 template <
class E,
class G>
2244 struct transition_eg<front::event<E>, G> {
2246 auto operator/(
const T &t)
const {
2247 return transition<front::event<E>, G, aux::zero_wrapper<T>>{e, g, aux::zero_wrapper<T>{t}};
2252 template <
class E,
class A>
2253 struct transition_ea<front::event<E>, A> {
2257 template <
class S1,
class S2,
class G,
class A>
2258 struct transition<state<S1>, transition<state<S2>, G, A>>
2259 : transition<state<S1>, state<S2>, front::event<back::anonymous>, G, A> {
2260 transition(
const state<S1> &,
const transition<state<S2>, G, A> &t)
2261 : transition<state<S1>, state<S2>, front::event<back::anonymous>, G, A>{t.g, t.a} {}
2263 template <
class S1,
class E,
class G,
class A>
2264 struct transition<state<S1>, transition<front::event<E>, G, A>>
2265 : transition<state<internal>, state<S1>, front::event<E>, G, A> {
2266 using transition<state<internal>, state<S1>, front::event<E>, G, A>::g;
2267 using transition<state<internal>, state<S1>, front::event<E>, G, A>::a;
2268 transition(
const state<S1> &,
const transition<front::event<E>, G, A> &t)
2269 : transition<state<internal>, state<S1>, front::event<E>, G, A>{t.g, t.a} {}
2271 auto operator=(
const T &)
const {
2272 return transition<T, state<S1>, front::event<E>, G, A>{g, a};
2275 template <
class S1,
class S2,
class E>
2276 struct transition<state<S1>, transition<state<S2>, front::event<E>>>
2277 : transition<state<S1>, state<S2>, front::event<E>, always, none> {
2278 transition(
const state<S1> &,
const transition<state<S2>, front::event<E>> &)
2279 : transition<state<S1>, state<S2>, front::event<E>, always, none>{always{}, none{}} {}
2281 template <
class S1,
class S2,
class G>
2282 struct transition<state<S1>, transition_sg<state<S2>, G>>
2283 : transition<state<S1>, state<S2>, front::event<back::anonymous>, G, none> {
2284 transition(
const state<S1> &,
const transition_sg<state<S2>, G> &t)
2285 : transition<state<S1>, state<S2>, front::event<back::anonymous>, G, none>{t.g, none{}} {}
2287 template <
class S1,
class S2,
class A>
2288 struct transition<state<S1>, transition_sa<state<S2>, A>>
2289 : transition<state<S1>, state<S2>, front::event<back::anonymous>, always, A> {
2290 transition(
const state<S1> &,
const transition_sa<state<S2>, A> &t)
2291 : transition<state<S1>, state<S2>, front::event<back::anonymous>, always, A>{always{}, t.a} {}
2293 template <
class S2,
class E,
class G>
2294 struct transition<state<S2>, transition_eg<front::event<E>, G>>
2295 : transition<state<internal>, state<S2>, front::event<E>, G, none> {
2296 using transition<state<internal>, state<S2>, front::event<E>, G, none>::g;
2297 transition(
const state<S2> &,
const transition_eg<front::event<E>, G> &t)
2298 : transition<state<internal>, state<S2>, front::event<E>, G, none>{t.g, none{}} {}
2300 auto operator=(
const T &)
const {
2301 return transition<T, state<S2>, front::event<E>, G, none>{g, none{}};
2304 template <
class S1,
class S2,
class E,
class G>
2305 struct transition<state<S1>, transition<state<S2>, transition_eg<front::event<E>, G>>>
2306 : transition<state<S1>, state<S2>, front::event<E>, G, none> {
2307 transition(
const state<S1> &,
const transition<state<S2>, transition_eg<front::event<E>, G>> &t)
2308 : transition<state<S1>, state<S2>, front::event<E>, G, none>{t.g, none{}} {}
2310 template <
class S2,
class E,
class A>
2311 struct transition<state<S2>, transition_ea<front::event<E>, A>>
2312 : transition<state<internal>, state<S2>, front::event<E>, always, A> {
2313 using transition<state<internal>, state<S2>, front::event<E>, always, A>::a;
2314 transition(
const state<S2> &,
const transition_ea<front::event<E>, A> &t)
2315 : transition<state<internal>, state<S2>, front::event<E>, always, A>{always{}, t.a} {}
2317 auto operator=(
const T &)
const {
2318 return transition<T, state<S2>, front::event<E>, always, A>{always{}, a};
2321 template <
class S1,
class S2,
class E,
class A>
2322 struct transition<state<S1>, transition<state<S2>, transition_ea<front::event<E>, A>>>
2323 : transition<state<S1>, state<S2>, front::event<E>, always, A> {
2324 transition(
const state<S1> &,
const transition<state<S2>, transition_ea<front::event<E>, A>> &t)
2325 : transition<state<S1>, state<S2>, front::event<E>, always, A>{always{}, t.a} {}
2327 template <
class S1,
class S2,
class E,
class G,
class A>
2328 struct transition<state<S1>, transition<state<S2>, transition<front::event<E>, G, A>>>
2329 : transition<state<S1>, state<S2>, front::event<E>, G, A> {
2330 transition(
const state<S1> &,
const transition<state<S2>, transition<front::event<E>, G, A>> &t)
2331 : transition<state<S1>, state<S2>, front::event<E>, G, A>{t.g, t.a} {}
2333 template <
class T,
class TSubs,
class... Ts,
class... THs>
2334 void update_composite_states(TSubs &subs, aux::true_type,
const aux::type_list<THs...> &) {
2335 using state_t =
typename T::state_t;
2336 auto &sm = back::sub_sm<T>::get(&subs);
2338 #if defined(__cpp_fold_expressions) 2339 ((sm.current_state_[aux::get_id<state_t, THs>((
typename T::initial_states_ids_t *)0)] =
2340 aux::get_id<state_t, THs>((
typename T::states_ids_t *)0)),
2343 (void)aux::swallow{0, (sm.current_state_[aux::get_id<state_t, THs>((
typename T::initial_states_ids_t *)0)] =
2344 aux::get_id<state_t, THs>((
typename T::states_ids_t *)0),
2348 template <
class T,
class TSubs,
class... Ts>
2349 void update_composite_states(TSubs &subs, aux::false_type, Ts &&...) {
2350 back::sub_sm<T>::get(&subs).initialize(
typename T::initial_states_t{});
2352 template <
class SM,
class TDeps,
class TSubs,
class TSrcState,
class TDstState>
2353 void update_current_state(SM &, TDeps &deps, TSubs &,
typename SM::state_t ¤t_state,
2354 const typename SM::state_t &new_state,
const TSrcState &,
const TDstState &) {
2355 back::policies::log_state_change<typename SM::sm_t>(aux::type<typename SM::logger_t>{}, deps,
2356 aux::string<typename TSrcState::type>{},
2357 aux::string<typename TDstState::type>{});
2358 current_state = new_state;
2360 template <
class SM,
class TDeps,
class TSubs,
class TSrcState,
class T>
2361 void update_current_state(SM &, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state,
2362 const typename SM::state_t &new_state,
const TSrcState &,
const state<back::sm<T>> &) {
2363 back::policies::log_state_change<typename SM::sm_t>(aux::type<typename SM::logger_t>{}, deps,
2364 aux::string<typename TSrcState::type>{}, aux::string<T>{});
2365 current_state = new_state;
2366 update_composite_states<back::sm_impl<T>>(subs,
typename back::sm_impl<T>::has_history_states{},
2367 typename back::sm_impl<T>::history_states_t{});
2369 template <
class TDeps,
class TSubs,
class TDstState>
2370 void process_internal_transitions(TDeps &, TSubs &,
const TDstState &) {}
2371 template <
class TDeps,
class TSubs,
class T>
2372 void process_internal_transitions(TDeps &deps, TSubs &subs,
const state<back::sm<T>> &) {
2373 auto &sm = back::sub_sm<back::sm_impl<T>>::get(&subs);
2374 while (sm.process_internal_events(back::anonymous{}, deps, subs)) {
2377 template <
class S1,
class S2,
class E,
class G,
class A>
2378 struct transition<state<S1>, state<S2>, front::event<E>, G, A> {
2379 static constexpr
auto initial = state<S2>::initial;
2380 static constexpr
auto history = state<S2>::history;
2386 using deps = aux::apply_t<aux::unique_t, aux::join_t<get_deps_t<G, E>, get_deps_t<A, E>>>;
2387 transition(
const G &g,
const A &a) : g(g), a(a) {}
2388 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
2389 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state, aux::true_type) {
2390 if (call<TEvent, args_t<G, TEvent>,
typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2391 sm.process_internal_event(back::on_exit<back::_, TEvent>{
event}, deps, subs, current_state);
2392 update_current_state(sm, deps, subs, current_state,
2393 aux::get_id<typename SM::state_t, dst_state>((
typename SM::states_ids_t *)0), state<src_state>{},
2394 state<dst_state>{});
2395 call<TEvent, args_t<A, TEvent>,
typename SM::logger_t>::execute(a, event, sm, deps, subs);
2396 sm.process_internal_event(back::on_entry<back::_, TEvent>{
event}, deps, subs, current_state);
2397 process_internal_transitions(deps, subs, state<dst_state>{});
2402 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
2403 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state, aux::false_type) {
2404 if (call<TEvent, args_t<G, TEvent>,
typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2405 update_current_state(sm, deps, subs, current_state,
2406 aux::get_id<typename SM::state_t, dst_state>((
typename SM::states_ids_t *)0), state<src_state>{},
2407 state<dst_state>{});
2408 call<TEvent, args_t<A, TEvent>,
typename SM::logger_t>::execute(a, event, sm, deps, subs);
2409 process_internal_transitions(deps, subs, state<dst_state>{});
2417 template <
class S2,
class E,
class G,
class A>
2418 struct transition<state<internal>, state<S2>, front::event<E>, G, A> {
2419 static constexpr
auto initial = state<S2>::initial;
2420 static constexpr
auto history = state<S2>::history;
2422 using dst_state =
internal;
2426 using deps = aux::apply_t<aux::unique_t, aux::join_t<get_deps_t<G, E>, get_deps_t<A, E>>>;
2427 transition(
const G &g,
const A &a) : g(g), a(a) {}
2428 template <
class TEvent,
class SM,
class TDeps,
class TSubs,
class... Ts>
2429 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t &, Ts &&...) {
2430 if (call<TEvent, args_t<G, TEvent>,
typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2431 call<TEvent, args_t<A, TEvent>,
typename SM::logger_t>::execute(a, event, sm, deps, subs);
2439 template <
class S1,
class S2,
class E,
class A>
2440 struct transition<state<S1>, state<S2>, front::event<E>, always, A> {
2441 static constexpr
auto initial = state<S2>::initial;
2442 static constexpr
auto history = state<S2>::history;
2446 using guard = always;
2448 using deps = aux::apply_t<aux::unique_t, get_deps_t<A, E>>;
2449 transition(
const always &,
const A &a) : a(a) {}
2450 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
2451 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state, aux::true_type) {
2452 sm.process_internal_event(back::on_exit<back::_, TEvent>{
event}, deps, subs, current_state);
2453 update_current_state(sm, deps, subs, current_state,
2454 aux::get_id<typename SM::state_t, dst_state>((
typename SM::states_ids_t *)0), state<src_state>{},
2455 state<dst_state>{});
2456 call<TEvent, args_t<A, TEvent>,
typename SM::logger_t>::execute(a, event, sm, deps, subs);
2457 sm.process_internal_event(back::on_entry<back::_, TEvent>{
event}, deps, subs, current_state);
2458 process_internal_transitions(deps, subs, state<dst_state>{});
2461 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
2462 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state, aux::false_type) {
2463 update_current_state(sm, deps, subs, current_state,
2464 aux::get_id<typename SM::state_t, dst_state>((
typename SM::states_ids_t *)0), state<src_state>{},
2465 state<dst_state>{});
2466 call<TEvent, args_t<A, TEvent>,
typename SM::logger_t>::execute(a, event, sm, deps, subs);
2467 process_internal_transitions(deps, subs, state<dst_state>{});
2472 template <
class S2,
class E,
class A>
2473 struct transition<state<internal>, state<S2>, front::event<E>, always, A> {
2474 static constexpr
auto initial = state<S2>::initial;
2475 static constexpr
auto history = state<S2>::history;
2477 using dst_state =
internal;
2479 using guard = always;
2481 using deps = aux::apply_t<aux::unique_t, get_deps_t<A, E>>;
2482 transition(
const always &,
const A &a) : a(a) {}
2483 template <
class TEvent,
class SM,
class TDeps,
class TSubs,
class... Ts>
2484 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t &, Ts &&...) {
2485 call<TEvent, args_t<A, TEvent>,
typename SM::logger_t>::execute(a, event, sm, deps, subs);
2490 template <
class S1,
class S2,
class E,
class G>
2491 struct transition<state<S1>, state<S2>, front::event<E>, G, none> {
2492 static constexpr
auto initial = state<S2>::initial;
2493 static constexpr
auto history = state<S2>::history;
2498 using action = none;
2499 using deps = aux::apply_t<aux::unique_t, get_deps_t<G, E>>;
2500 transition(
const G &g,
const none &) : g(g) {}
2501 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
2502 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state, aux::true_type) {
2503 if (call<TEvent, args_t<G, TEvent>,
typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2504 sm.process_internal_event(back::on_exit<back::_, TEvent>{
event}, deps, subs, current_state);
2505 update_current_state(sm, deps, subs, current_state,
2506 aux::get_id<typename SM::state_t, dst_state>((
typename SM::states_ids_t *)0), state<src_state>{},
2507 state<dst_state>{});
2508 sm.process_internal_event(back::on_entry<back::_, TEvent>{
event}, deps, subs, current_state);
2509 process_internal_transitions(deps, subs, state<dst_state>{});
2514 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
2515 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state, aux::false_type) {
2516 if (call<TEvent, args_t<G, TEvent>,
typename SM::logger_t>::execute(g, event, sm, deps, subs)) {
2517 update_current_state(sm, deps, subs, current_state,
2518 aux::get_id<typename SM::state_t, dst_state>((
typename SM::states_ids_t *)0), state<src_state>{},
2519 state<dst_state>{});
2520 process_internal_transitions(deps, subs, state<dst_state>{});
2527 template <
class S2,
class E,
class G>
2528 struct transition<state<internal>, state<S2>, front::event<E>, G, none> {
2529 static constexpr
auto initial = state<S2>::initial;
2530 static constexpr
auto history = state<S2>::history;
2532 using dst_state =
internal;
2535 using action = none;
2536 using deps = aux::apply_t<aux::unique_t, get_deps_t<G, E>>;
2537 transition(
const G &g,
const none &) : g(g) {}
2538 template <
class TEvent,
class SM,
class TDeps,
class TSubs,
class... Ts>
2539 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t &, Ts &&...) {
2540 return call<TEvent, args_t<G, TEvent>,
typename SM::logger_t>::execute(g, event, sm, deps, subs);
2544 template <
class S1,
class S2,
class E>
2545 struct transition<state<S1>, state<S2>, front::event<E>, always, none> {
2546 static constexpr
auto initial = state<S2>::initial;
2547 static constexpr
auto history = state<S2>::history;
2551 using guard = always;
2552 using action = none;
2553 using deps = aux::type_list<>;
2554 transition(
const always &,
const none &) {}
2555 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
2556 bool execute(
const TEvent &event, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state, aux::true_type) {
2557 sm.process_internal_event(back::on_exit<back::_, TEvent>{
event}, deps, subs, current_state);
2558 update_current_state(sm, deps, subs, current_state,
2559 aux::get_id<typename SM::state_t, dst_state>((
typename SM::states_ids_t *)0), state<src_state>{},
2560 state<dst_state>{});
2561 sm.process_internal_event(back::on_entry<back::_, TEvent>{
event}, deps, subs, current_state);
2562 process_internal_transitions(deps, subs, state<dst_state>{});
2565 template <
class TEvent,
class SM,
class TDeps,
class TSubs>
2566 bool execute(
const TEvent &, SM &sm, TDeps &deps, TSubs &subs,
typename SM::state_t ¤t_state, aux::false_type) {
2567 update_current_state(sm, deps, subs, current_state,
2568 aux::get_id<typename SM::state_t, dst_state>((
typename SM::states_ids_t *)0), state<src_state>{},
2569 state<dst_state>{});
2570 process_internal_transitions(deps, subs, state<dst_state>{});
2573 __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
2575 template <
class S2,
class E>
2576 struct transition<state<internal>, state<S2>, front::event<E>, always, none> {
2577 static constexpr
auto initial = state<S2>::initial;
2578 static constexpr
auto history = state<S2>::history;
2580 using dst_state =
internal;
2582 using guard = always;
2583 using action = none;
2584 using deps = aux::type_list<>;
2585 transition(
const always &,
const none &) {}
2586 template <
class TEvent,
class SM,
class TDeps,
class TSubs,
class... Ts>
2587 bool execute(
const TEvent &, SM &, TDeps &, TSubs &,
typename SM::state_t &, Ts &&...) {
2590 __BOOST_SML_ZERO_SIZE_ARRAY(aux::byte);
2594 #if !defined(COMPILING_WITH_MSVC) 2595 template <
class TEvent>
2596 constexpr front::event<TEvent>
event{};
2598 template <
class TEvent>
2599 front::event<TEvent>
event __BOOST_SML_VT_INIT;
2601 template <
class TEvent>
2602 __BOOST_SML_UNUSED front::event<back::on_entry<_, TEvent>> on_entry __BOOST_SML_VT_INIT;
2603 template <
class TEvent>
2604 __BOOST_SML_UNUSED front::event<back::on_exit<_, TEvent>> on_exit __BOOST_SML_VT_INIT;
2605 template <
class TEvent>
2606 front::event<back::unexpected_event<TEvent>> unexpected_event __BOOST_SML_VT_INIT;
2608 front::event<back::exception<T>> exception __BOOST_SML_VT_INIT;
2609 using anonymous = back::anonymous;
2610 using initial = back::initial;
2611 #if !defined(COMPILING_WITH_MSVC) 2618 inline namespace literals {
2619 #if !defined(COMPILING_WITH_MSVC) 2620 template <
class T, T... Chrs>
2621 constexpr
auto operator""_s() {
2622 return front::state<aux::string<T, Chrs...>>{};
2624 template <
class T, T... Chrs>
2625 constexpr
auto operator""_e() {
2626 return event<aux::string<T, Chrs...>>;
2630 __BOOST_SML_UNUSED
static front::state<back::terminate_state> X;
2631 __BOOST_SML_UNUSED
static front::history_state H;
2632 __BOOST_SML_UNUSED
static front::actions::defer defer;
2633 __BOOST_SML_UNUSED
static front::actions::process process;
2634 template <
class... Ts, __BOOST_SML_REQUIRES(aux::is_same<aux::bool_list<aux::always<Ts>::value...>,
2635 aux::bool_list<concepts::transitional<Ts>::value...>>::value)>
2636 auto make_transition_table(Ts... ts) {
2637 return aux::pool<Ts...>{ts...};
2639 BOOST_SML_NAMESPACE_END
2640 #undef __BOOST_SML_UNUSED 2641 #undef __BOOST_SML_VT_INIT 2642 #undef __BOOST_SML_ZERO_SIZE_ARRAY 2643 #undef __BOOST_SML_ZERO_SIZE_ARRAY_CREATE 2644 #undef __BOOST_SML_TEMPLATE_KEYWORD 2645 #if defined(__clang__) 2646 #pragma clang diagnostic pop 2647 #elif defined(__GNUC__) 2648 #undef __has_builtin 2649 #pragma GCC diagnostic pop 2650 #elif defined(COMPILING_WITH_MSVC) 2651 #undef __has_builtin 2652 #undef __has_builtin__make_integer_seq 2654 #undef COMPILING_WITH_MSVC bool operator<=(socket_ref a, socket_ref b) ZMQ_NOTHROW