0

Could somebody say a good example of usage of State machine in software (except compilators and parsers)? There are examples of a great practical importance and usage of state machine should simplify software:-)

I want to write .NET application.

Thanks.

evgeny-i
  • 50
  • 8
  • see http://stackoverflow.com/questions/255797/uses-for-state-machines. not quite a duplicate, although not sure – CharlesB Apr 20 '12 at 20:15

9 Answers9

1

You can think of every UI you see as one big state machine. Every event from the UI (e.g. button click, menu selection, etc.) drives a transition to another state, which could mean a new page.

duffymo
  • 305,152
  • 44
  • 369
  • 561
1

Your OS kernel scheduler/dispatcher is a state machine. The threads have states - running, ready, sleeping, eventWaiting, suspended, terminated. The events are the hardware interrupts from IO device drivers and software interrupts from running threads.

Martin James
  • 24,453
  • 3
  • 36
  • 60
1

Web site design showing typical navigation paths (similar to @duffymo's answer). Here's an incomplete example (inspired from "Applying UML and Patterns" (Craig Larman)):

enter image description here

Fuhrmanator
  • 11,459
  • 6
  • 62
  • 111
0

Another scenario is ordering. A new order (in new state) can be cancelled or modified, but not refunded. But, once you have it in completed state, it can not be cancelled, but it might be refunded.

AD.Net
  • 13,352
  • 2
  • 28
  • 47
0

Random number generator can somehow be considered also as a state machine. You have a set of inputs like shift left, add constant, multiply by a constant etc. A state is an actual current random value. Since the count of such random numbers is finite, it can be considered as a some kind of finite state machine.

0

The opengl library is a state machine. It keeps a status that changes depending on the calls to the library functions. You can see it here: http://www.cs.tufts.edu/research/graphics/resources/OpenGL/OpenGL.htm

Another scope in which the state machines could be used is in video games. Imagine one enemy that is relatively intelligent. This enemy will have several statuses: attacking, hiding, dying, running, etc. This could be controlled by states and events. When I wrote a video game as my degree project I used two state machines: one for the game flow (presentation screen, game, options, etc) and the other for the game itself (asking question, throwing the dice, moving player, etc)

0

Here is a toy console app example of a basic FSM.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

//  DESC: QAD-FSM (Quick And Dirty Finite State Machine)
//  
//  Notes: In its simplest form a state machine is
//       • A set of states
//       • A set of events
//       • A set of transitions that define 
//           the next state given the current state and event.
//       • A method of tracking current state
// 
//  Example:
// 
//       I want to create a different kind of door lock that
//           has the following states:
//          
//               1. LBS - Locked_Both_Sides
//               2. UBS - Unlocked_Both_Sides
//               3. LFO - Locked_From_Outside
// 
//           and has the following events:
//          
//               1. OKT - Outside Key Turn
//               2. IKT - Inside Key Turn
//              
//       Transistions will be as follows:
//      
//       CurrState  Event   NextState   Desc
//       ========================================================
//       LBS            OKT     UBS         When both sides locked, outside key turn unlocks both sides
//       LBS            IKT     LFO         When both sides locked, inside key turn unlocks inside
//       UBS            OKT     LFO         When both sides unlocked, outside key turn locks outside
//       UBS            IKT     LBS         When both sides unlocked, inside key turn locks both sides
//       LFO            OKT     UBS         When only outside locked, outside key turn unlocks outside
//       LFO            IKT     LBS         When only outside locked, inside key turn locks both sides.

namespace FSM
{
    // The FSM states
    enum State
    {
        LBS,
        UBS,
        LFO
    }

    // The FSM events
    enum Event
    {
        IKT,
        OKT
    }

    class Transition
    {
        public State currState { get; set; }
        public Event evnt { get; set; }
        public State nextState { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var fsm = new FSM();

            System.Console.WriteLine("Current State: " + fsm.StateDesc[fsm.CurrentState]);

            string input = "";
            while (input != "x")
            {
                System.Console.Write("Enter key turn [IKT, OKT] or x to exit: ");
                input = System.Console.ReadLine();
                if (input == "x") break;
                Event evnt;
                if (!Enum.TryParse(input, out evnt))
                {
                    System.Console.WriteLine("Invalid input: " + input + ", enter one of [IKT,OKT,x]");
                    continue;
                }
                fsm.ChangeState(evnt);
                System.Console.WriteLine("New State: " + fsm.StateDesc[fsm.CurrentState]);
            }

            System.Console.WriteLine("");
            System.Console.WriteLine("History");
            System.Console.WriteLine("===============================================");
            System.Console.WriteLine("CurrState(Event) => NextState");
            System.Console.WriteLine("===============================================");
            fsm.hist
                .Select(h => h.currState.ToString() + "(" + h.evnt.ToString() + ") => " + h.nextState.ToString())
                .ToList()
                .ForEach(h => System.Console.WriteLine(h));
        }
    }

    class FSM
    {
        public Dictionary<State, String> StateDesc = new Dictionary<State, String>()
                                                { 
                                                    {State.LBS, "Both Sides Locked"},
                                                    {State.LFO, "Locked From Outside"},
                                                    {State.UBS, "Both Sides Unlocked"}
                                                };

        public List<Transition> hist = new List<Transition>();

        // Create FSM transitions.
        List<Transition> trans = new List<Transition>
            {
                new Transition() { currState = State.LBS, evnt = Event.OKT, nextState = State.UBS }, 
                new Transition() { currState = State.LBS, evnt = Event.IKT, nextState = State.LFO }, 
                new Transition() { currState = State.UBS, evnt = Event.OKT, nextState = State.LFO }, 
                new Transition() { currState = State.UBS, evnt = Event.IKT, nextState = State.LBS }, 
                new Transition() { currState = State.LFO, evnt = Event.OKT, nextState = State.UBS }, 
                new Transition() { currState = State.LFO, evnt = Event.IKT, nextState = State.LBS }, 
            };

        public State CurrentState { get { var lt = hist.FirstOrDefault(); return lt == null ? State.UBS : lt.nextState; } }

        public State? ChangeState(Event evnt)
        {
            var t = trans.Find(r => r.currState == CurrentState && r.evnt == evnt);
            if (t == null) return null; // If you don't create transitions that cover all combinations this could happen.
            hist.Insert(0, t);
            return t.nextState;
        }
    }
}
cyberman
  • 33
  • 1
  • 6
0

You can see my Generic State Machine in .net using Aspect-Oriented-Programming as an example of implementation.

It can be used in a software that need some workflow logic like an approval workflow.

https://github.com/rcarubbi/carubbi.statemachine

Just create your entity like this:

    [InitialState("State1")]
    public class Entity : IStatedEntity
    {

        [Transition(From = "State1", To = "State2")]
        [Transition(From = "State3", To = "State1")]
        public void Method1()
        {
            Trace.WriteLine("Method1");
        }

        [Transition(From = "State2", To = "State1")]
        public string Method2()
        {
            Trace.WriteLine("Method2");
            return string.Empty;
        }

        [Transition(From = "State2", To = "State3")]
        [Transition(From = "State3", To = "State4")]
        public int Method3(int p1, int p2)
        {
            Trace.WriteLine("Method3");
            return p1 + p2;
        }


        public StateMachine StateMachine { get; set; }
   }

and use it this way:

      [TestMethod]
        public void TestMethod1()
        {
            StateMachine.Configure();
            var ent = new Entity
            {
                StateMachine =
                {
                    IgnoreInvalidOperations = true
                }
            };

            ent.StateMachine.TransitionStarted += StateMachine_TransitionStarted;
            ent.StateMachine.TransitionEnded += StateMachine_TransitionEnded;

            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method1();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method2();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            ent.Method1();
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result = ent.Method3(2, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result2 = ent.Method3(4, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
            var result3 = ent.Method3(4, 4);
            Trace.WriteLine(ent.StateMachine.CurrentState);
        }

        private void StateMachine_TransitionEnded(object sender, TransitionEventArgs e)
        {

        }


        private void StateMachine_TransitionStarted(object sender, TransitionStartedEventArgs e)
        {

        }
   }
rcarubbi
  • 123
  • 1
  • 10