예제 #1
0
        ///// <summary>
        ///// Provides a mechanism to stop the finite state machine.
        ///// It will cause the method <see cref="RunStateMachine()"/> to complete so that the thread in which it runs can stop too.
        /////
        ///// Note that for finite state machine designs that raise events in the event handlers,
        ///// you must have a Stopping event handler as part of your state machine design.
        ///// The code in the Stopping event must not raise any events and Stop() should be called from within that handler.
        ///// </summary>
        //public void Stop()
        //{
        //    string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;
        //    if (log.IsDebugEnabled)
        //        log.Debug($"{methodName}: enter");

        //    stopRequested = true;
        //    lock (locker)
        //    {
        //        Monitor.Pulse(locker); // Wakes up the state machine thread if it is sleeping.
        //    }

        //    if (log.IsDebugEnabled)
        //        log.Debug($"{methodName}: exit");
        //}

        /// <summary>
        /// Sets the current state of the finite state machine.
        /// </summary>
        /// <param name="toState">The finite state that we want to become the current state.</param>
        /// <exception cref="ArgumentException">Thrown if the parameter toState is a finite state that has not been added by <see cref="AddState(FiniteState)"/></exception>
        public void SetCurrentState(FiniteState toState)
        {
            string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;

            if (log.IsDebugEnabled)
            {
                log.Debug($"{methodName}: enter");
            }

            if (!ManagedStates.TryGetValue(toState.Name, out FiniteState currentStateCandidate))
            {
                throw new ArgumentException($"Attempted to set current state to '{toState.Name}' but no state of that name is managed by this state machine.");
            }
            CurrentState = currentStateCandidate;

            if (log.IsInfoEnabled)
            {
                log.Info($"{methodName}: changed to [{CurrentState.Name}]");
            }

            if (log.IsDebugEnabled)
            {
                log.Debug($"{methodName}: exit");
            }
        }
예제 #2
0
        /// <summary>
        /// Add a new FiniteState to the collection of states managed by this state machine.
        /// </summary>
        /// <param name="StateToAdd">The finite state to add.</param>
        /// <returns>A reference to the finite state that was just added.</returns>
        /// <exception cref="ArgumentException">Thrown if you try to add a finite state that has already been added.</exception>
        public FiniteState AddState(FiniteState StateToAdd)
        {
            string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;

            try
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug($"{methodName}: enter");
                }

                if (ManagedStates.ContainsKey(StateToAdd.Name))
                {
                    throw new ArgumentException($"Attempt to add a duplicate state '{StateToAdd.Name}'.");
                }

                if (log.IsInfoEnabled)
                {
                    log.Info($"{methodName}: [{StateToAdd.Name}]");
                }

                ManagedStates.Add(StateToAdd.Name, StateToAdd);
                return(StateToAdd);
            }
            finally
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug($"{methodName}: exit");
                }
            }
        }
        /// <summary>
        /// Starts the state machine.
        ///
        /// Every state diagram has a start state with a single transition to some initial state in the diagram via a start event.
        /// This method performs the following actions:
        ///  * creates the start state
        ///  * creates the start event
        ///  * adds a transition from the start state, via the start event to InitialState, the finite state passed as a parameter
        ///  * sets the current state to be the start state
        ///  * raises the start event
        ///    The OnEntry event handler for InitialState will be executed.
        ///    The state machine is now sitting in it's initial state and waiting for an event to occur.
        /// </summary>
        /// <param name="InitialState">The finite state in which this state machine starts.</param>
        public void Start(FiniteState InitialState)
        {
            string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;

            if (log.IsDebugEnabled)
            {
                log.Debug($"{methodName}: enter");
            }

            engine.Start(InitialState);

            if (log.IsDebugEnabled)
            {
                log.Debug($"{methodName}: exit");
            }
        }
        /// <summary>
        /// Create and add a new FiniteState to the collection of states managed by this state machine.
        /// </summary>
        /// <param name="Name">The name finite state to create and add.</param>
        /// <returns>A reference to the finite state that was just created and added.</returns>
        /// <exception cref="ArgumentException">Thrown if you try to add a finite state that has already been added.</exception>
        public FiniteState AddState(string Name)
        {
            string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;

            try
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug($"{methodName}: enter");
                }
                FiniteState stateToAdd = new FiniteState(Name);
                return(engine.AddState(stateToAdd));
            }
            finally
            {
                if (log.IsDebugEnabled)
                {
                    log.Debug($"{methodName}: exit");
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Starts the state machine.
        ///
        /// Every state diagram has a start state with a single transition to some initial state in the diagram via a start event.
        /// This method performs the following actions:
        ///  * creates the start state
        ///  * creates the start event
        ///  * adds a transition from the start state, via the start event to InitialState, the finite state passed as a parameter
        ///  * sets the current state to be the start state
        ///  * raises the start event
        ///    The OnEntry event handler for InitialState will be executed.
        ///    The state machine is now sitting in it's initial state and waiting for an event to occur.
        ///
        /// On a technical note, the underlying Thread, in which the event handlers are run, is also created and started here.
        /// </summary>
        /// <param name="InitialState">The finite state in which this state machine starts.</param>
        /// <exception cref="ArgumentException">Thrown if the parameter InitialState is a finite state that has not been added by <see cref="AddState(FiniteState)"/></exception>
        public void Start(FiniteState InitialState)
        {
            string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name;

            if (log.IsDebugEnabled)
            {
                log.Debug($"{methodName}: enter");
            }

            //if (OnExceptionAction == null)
            //{
            //    throw new ArgumentException($"The state machine must have an OnExceptionAction before you can start it.");
            //}

            //
            //  Perform sanity checks
            //
            foreach (KeyValuePair <string, FiniteState> kvp in ManagedStates)
            {
                //
                //  1. Make sure each finite state has an OnEnterAction
                //
                FiniteState finiteState = kvp.Value;
                if (finiteState.OnEnterAction == null)
                {
                    throw new Exception($"The finite state, '{finiteState.Name}' does not have an OnEnterAction.");
                }
                //
                //  2. Make sure the target state in every transition has been added to the state machine.
                //
                foreach (KeyValuePair <string, FiniteStateTransition> transitionKvp in finiteState.Transitions)
                {
                    FiniteStateTransition fst = transitionKvp.Value;
                    string stateName          = fst.ToState.Name;
                    if (!ManagedStates.ContainsKey(stateName))
                    {
                        throw new Exception($"The finite state, '{stateName}' has not been added to the state machine.");
                    }
                }
            }

            FiniteState      startState = new FiniteState(START_STATE_NAME);
            FiniteStateEvent startEvent = new FiniteStateEvent(START_EVENT_NAME);

            startState.OnEnterAction = () => { }; // needs an empty handler
            AddState(startState);
            startState.AddTransition(startEvent, InitialState);
            SetCurrentState(startState);
            RaiseEvent(startEvent);

            //Thread runner = new Thread(RunStateMachine)
            //{
            //    Name = Name
            //};
            //runner.Start();

            if (log.IsDebugEnabled)
            {
                log.Debug($"{methodName}: exit");
            }
        }
예제 #6
0
 /// <summary>
 /// Add a new transition to the collection of transitions from this state that is created from an event and a state.
 /// </summary>
 /// <param name="ViaEvent">The event that will trigger this transition.</param>
 /// <param name="ToState">The state that is the destination of the transition.</param>
 /// <exception cref="ArgumentException">Thrown if the event in TransitionToAdd has already been used in a transition from this state.</exception>
 public void AddTransition(FiniteStateEvent ViaEvent, FiniteState ToState)
 {
     AddTransition(new FiniteStateTransition(ViaEvent, ToState));
 }
예제 #7
0
 public void start(FiniteState startState)
 {
     engine.Start(startState);
 }