@@ -511,7 +511,7 @@ public:
511511 AssertionProviderType::Assert (impl_ != nullptr ); // Most probably you forgot to call Init()
512512 current_state_ = &kInTransition ;
513513 initial_.clear ();
514- EnterStatesFromDownTo (nullptr , initial, {});
514+ EnterStatesFromDownTo (nullptr , initial, false , {});
515515 }
516516
517517 /* *
@@ -528,6 +528,7 @@ public:
528528 Transition transition (kInTransition );
529529 const auto * start = current_state_;
530530 const auto * s = current_state_;
531+ bool is_self_transition = false ;
531532
532533 do
533534 {
@@ -544,9 +545,17 @@ public:
544545 working_ = false ;
545546 return ;
546547 }
548+ if (transition.target_ != nullptr )
549+ {
550+ if (transition.target_ == s)
551+ {
552+ is_self_transition = true ;
553+ }
554+ break ;
555+ }
547556
548557 s = s->parent_ ;
549- } while ((transition. target_ == nullptr ) && ( s != nullptr ) );
558+ } while (s != nullptr );
550559
551560 if ((transition.target_ != nullptr ))
552561 {
@@ -562,9 +571,9 @@ public:
562571 on_state_change_ (*this , event, *old_state, *transition.target_ );
563572 }
564573
565- ExitStatesFromUpTo (old_state, common_parent, event);
574+ ExitStatesFromUpTo (old_state, common_parent, is_self_transition, event);
566575 transition.ExecuteActions (impl_, event);
567- EnterStatesFromDownTo (common_parent, transition.target_ , event);
576+ EnterStatesFromDownTo (common_parent, transition.target_ , is_self_transition, event);
568577 }
569578 else
570579 {
@@ -788,31 +797,29 @@ private:
788797 }
789798 }
790799
791- void ExitStatesFromUpTo (StatePtr from, StatePtr top, Event event)
800+ void ExitStatesFromUpTo (StatePtr from, StatePtr top, bool is_self_transition, Event event)
792801 {
793802 const auto * state = from;
794803
795- if (state = = top)
804+ while (state ! = top)
796805 {
797- ExitState (state, event);
798- }
799- else
800- {
801- while (state != top)
806+ // Save history state
807+ if (state->parent_ != nullptr )
802808 {
803- // Save history state
804- if (state->parent_ != nullptr )
809+ if ((state->parent_ ->flags_ & EFlags::kHistory ) != EFlags::kNone )
805810 {
806- if ((state->parent_ ->flags_ & EFlags::kHistory ) != EFlags::kNone )
807- {
808- SetInitialState (state->parent_ , state);
809- }
811+ SetInitialState (state->parent_ , state);
810812 }
813+ }
811814
812- ExitState (state, event);
815+ ExitState (state, event);
813816
814- state = state->parent_ ;
815- }
817+ state = state->parent_ ;
818+ }
819+
820+ if (is_self_transition)
821+ {
822+ ExitState (state, event);
816823 }
817824 }
818825
@@ -839,16 +846,19 @@ private:
839846 }
840847 }
841848
842- void EnterStatesFromDownTo (StatePtr top, StatePtr target, Event event)
849+ void EnterStatesFromDownTo (StatePtr top, StatePtr target, bool is_self_transition, Event event)
843850 {
844851 // Enter all states up to parent
845852 if (top != target)
846853 {
847854 EnterStatesFromDownToRecursive (top, target->parent_ , event);
855+ EnterState (*target, event);
848856 }
849-
850- // Alywas enter target state (we may have exited it, possibly a self transition)
851- EnterState (*target, event);
857+ else if (is_self_transition)
858+ {
859+ EnterState (*target, event);
860+ }
861+ // else: no enter when we have a direct transition from an inner state to a parent state
852862
853863 // Is target a hierarchical state? If so, enter initial state
854864 const auto * state = GetInitialState (target);
0 commit comments