Skip to content

Commit 35c4ae8

Browse files
committed
Added ability to enable direct state-to-state transitions to be used for state tracking external systems.
1 parent 67f120e commit 35c4ae8

File tree

1 file changed

+82
-0
lines changed

1 file changed

+82
-0
lines changed

FSM/FiniteStateMachine.hh

+82
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,41 @@ namespace Core
685685
}
686686

687687

688+
/**
689+
* Posts an event that will transition the FSM from it's current state
690+
* to the desired target state.
691+
*
692+
* @param target_state - the state to which the transition is to be made.
693+
*
694+
* @note The entry and exit functions do get executed, just like under normal
695+
* event handling conditions.
696+
*/
697+
inline void PostTransitionTo(
698+
StateID target_state
699+
)
700+
{
701+
Event trans( state_transfer_event + target_state );
702+
PostInternalEvent( trans );
703+
}
704+
705+
706+
/**
707+
* @return true if the event passed in is a direct state transfer
708+
* event, false otherwise.
709+
*
710+
* @note May be used to detect that a state transition occured
711+
* because of a direct transition rather than a user defined
712+
* event. This knowledge is useful when entry/exit functions
713+
* should behave differently when a direct transfer takes
714+
* place.
715+
*/
716+
bool IsDirectTransition(
717+
const Event & event
718+
)
719+
{
720+
return (EventNumber) event >= state_transfer_event;
721+
}
722+
688723
/**
689724
* @return the current state identifier of the FSM.
690725
*/
@@ -729,6 +764,50 @@ namespace Core
729764
current_state = new_state;
730765
}
731766

767+
/**
768+
* Used only when there is a need to perform transitions from any state
769+
* to any other state. In other words, this enables the user to perform
770+
* ad-hoc state transitions. That is useful in cases where the state
771+
* machine is to be tracking the actual state of an external system.
772+
* In that case it may be necessary to simply match the state of the
773+
* external system instead of transitioning the state machine.
774+
* It sets the event number that is used to perform direct state to state
775+
* transitions. The event number should be the largest positive number
776+
* assigned to events in the class. The method internally creates
777+
* additional event numbers based on the number of states in the class.
778+
*
779+
* This method should only be called after the states have been
780+
* configured and only if arbitrary state transitions are desired.
781+
* Note that the entry/exit functions do get called when the transitions
782+
* take place.
783+
*
784+
* @param event_number - the event number that serves as the state transfer
785+
* event.
786+
*/
787+
void SetStateTransferEvent( EventNumber event_number )
788+
{
789+
state_transfer_event = event_number;
790+
const size_t n_of_states = state_table.size();
791+
typename StateTable::iterator sit = state_table.begin();
792+
StateID sid = LowestValidStateID;
793+
for ( ; sit != state_table.end(); ++sit, ++sid )
794+
{
795+
State *state = *sit;
796+
assert( sid == *state );
797+
EventNumber e = event_number;
798+
for ( StateID s = LowestValidStateID; s < n_of_states; ++s, ++e )
799+
{
800+
if ( s == sid ) continue; // skip self transition
801+
// Make sure that the user selected an event number that is
802+
// the largest numeric value.
803+
if ( state->TransitionForEvent( e ) != SentinelStateID )
804+
{
805+
throw Exception("Bad state transfer event selection.");
806+
}
807+
state->SetTransition( e, s );
808+
}
809+
}
810+
}
732811

733812
protected :
734813
/// The states registered for this state machine are held in this type.
@@ -920,6 +999,9 @@ namespace Core
920999
///
9211000
EventHandler default_handler;
9221001

1002+
/// The event number that is used to transition between arbitrary
1003+
/// states.
1004+
EventNumber state_transfer_event;
9231005

9241006
private :
9251007
/**

0 commit comments

Comments
 (0)