@@ -685,6 +685,41 @@ namespace Core
685
685
}
686
686
687
687
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
+
688
723
/* *
689
724
* @return the current state identifier of the FSM.
690
725
*/
@@ -729,6 +764,50 @@ namespace Core
729
764
current_state = new_state;
730
765
}
731
766
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
+ }
732
811
733
812
protected :
734
813
// / The states registered for this state machine are held in this type.
@@ -920,6 +999,9 @@ namespace Core
920
999
// /
921
1000
EventHandler default_handler;
922
1001
1002
+ // / The event number that is used to transition between arbitrary
1003
+ // / states.
1004
+ EventNumber state_transfer_event;
923
1005
924
1006
private :
925
1007
/* *
0 commit comments