Skip to content

Commit 1185cd3

Browse files
committed
Fix bug in executing entry/exit actions in self-transitions
1 parent 70e2b42 commit 1185cd3

File tree

1 file changed

+34
-24
lines changed

1 file changed

+34
-24
lines changed

include/cpp_event_framework/Statemachine.hxx

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)