Constructing finite state machines for Linux applications

Source: Internet
Author: User
Tags close close fsm

Finite automata (finite automata machine) is an important cornerstone of computer science, which is commonly referred to as finite state machines (finite) in the field of software development, and is a widely used software design model Pattern). This article describes how to build a state machine-based software system, and how to use the tools under Linux to automatically generate a practical state machine framework.

First, what is the state machine

Finite state machine (FEM) is a tool for modeling object behavior, which mainly describes the sequence of States experienced by an object during its life cycle, and how to respond to various events from outside. In an object-oriented software system, no matter how simple or complex an object is, it inevitably undergoes a complete process from inception to eventual extinction, which is often referred to as the object's life cycle. In general, an object cannot be completely isolated during its lifetime, and it must affect other objects by sending messages, or alter itself by accepting messages. In most cases, these messages are just simple, synchronous method calls. For example, in a bank customer management system, an instance of the Customer class (client) might call the GetBalance () method defined in the account class when needed. In this simple case, the class customer does not need a finite state machine to describe its behavior, mainly because its current behavior does not depend on a state of the past.

Unfortunately not all things are so simple, in fact many practical software systems have to maintain one or two very critical objects, which often have very complex state transitions and need to respond to various asynchronous events from outside. For example, in a VoIP telephony system, an instance of the phone class (telephone) must be able to respond to random calls from each other, key events from the user, signaling from the network, and so on. When dealing with these messages, the behavior of the class telephone depends entirely on its current state, so using the state machine at this point is a good choice.

The game engine is one of the most successful applications of finite state machines, and because a well-designed state machine can be used to replace part of the AI algorithm, it is possible for each character or device in the game to embed a state machine. Consider a simple object such as a gate in the RPG game, which has four states of open (opened), Close (Closed), Lock (Locked), unlock (unlocked), and 1 shows. When the player arrives at a gate in the state locked, if at this time he has found the key to open the door, then he can use it to change the current state of the door to the unlocked, further can also through the rotary Gate of the handle to turn its state into opened, thus successfully entered the city.

Figure 1 State machine for controlling the gate

States, events, transitions, and actions are some of the basic concepts that are often encountered when describing finite state machines.

    • state refers to a condition in which an object is in its life cycle, and an object in a particular state is bound to satisfy certain conditions, perform certain actions, or wait for certain events.
    • Event refers to the things that occupy a certain place in time and space, and which are meaningful to the state machine. Events often cause changes in state, prompting the state machine to switch from one state to another.
    • conversion (Transition) refers to a relationship between two states, indicating that an object will perform a certain action in the first state and will enter a second state when an event occurs while a particular condition is satisfied.
    • Action refers to those atomic operations that can be performed in a state machine, which means that they cannot be interrupted by other messages while they are running, and must be executed all the time.

Back to top of page

Second, hand-written state machine

Unlike other commonly used design patterns, programmers want to add state machines to their own software systems and have to write some additional code for logic control, which is quite difficult to implement and maintain if the system is complex enough. Using a switch statement is the simplest and most straightforward way to implement a finite state, and the basic idea is to set up a case branch for each state in the state machine, specifically to control the state. The following code demonstrates how to use the switch statement to implement the state machine shown in Figure 1:

switch (state) {//Processing status opened branch case (opened): {//Execute action open open ();  Check if there is a Closedoor event if (Closedoor ()) {//Current state transitions to Closed changestate (Closed)} break;    }//Processing Status Closed branch case (Closed): {//execute action close close ();    Check if there is a Opendoor event if (Opendoor ()) {//Current state transitions to opened Changestate (opened);    }//Check if there is a Lockdoor event if (Lockdoor ()) {//Current state transitions to Locked changestate (Locked);  } break;    }//Processing Status Locked branch case (Locked): {//Execute Action Lock lock ();    Check if there is a Unlockdoor event if (Unlockdoor ()) {//Current state transitions to unlocked changestate (unlocked);  } break;    }//Processing Status Unlocked branch case (Unlocked): {//execute action unlock unlock ();        Check if there are Lockdoor events if (Lockdoor ()) {//Current state transitions to Locked changestate (Locked)}//Check for Opendoor events    if (Opendoor ()) {//current state is converted to opened Changesate (opened);  } break; }}

The finite state machines implemented with the switch statement do work well, but the readability of the code is not very good, mainly because the checks and transitions are mixed in the current state when the transitions between states are implemented. For example, when a city gate is in a opened state, it is necessary to call the Closedoor () function in the appropriate case to check if a state transition is necessary and, if so, to call the Changestate () function to switch the current state to closed. Obviously, if you need to check several different conversion conditions in each state, and you need to change the state machine to a different state depending on the result of the check, then this code will be boring and difficult to understand. From the point of view of code refactoring, it is better to introduce Checkstatechange () and Performstatechange () two functions, which are specifically used to examine the transition conditions and the various actions that need to be performed to activate the transformation. As a result, the program structure becomes clearer:

Switch (state)  {  //Processing status opened branch case  (opened): {    //Execute action Open    open ();    Check if there is an event that fires a state transition to produce    if (Checkstatechange ()) {      //convert state machine state to      Performstatechange ();    }    break;  }  Branch case (Closed) for processing status Closed  : {    //execute action close    close ();    Check if there is an event that fires a state transition to produce    if (Checkstatechange ()) {      //convert state machine state to      Performstatechange ();    }    break;  }  Branch case (Locked) for processing status Locked  : {    //execute Action Lock    Lock ();    Check if there is an event that fires a state transition to produce    if (Checkstatechange ()) {      //convert state machine state to      Performstatechange ();    }    break;  }  Branch case (unlocked) for processing status unlocked  : {    //execute action lock    unlock ();    Check if there is an event that fires a state transition to produce    if (Checkstatechange ()) {      //convert state machine state to      Performstatechange ();    }    break;  }}

But the two functions of Checkstatechange () and Performstatechange () themselves are still in the face of very complex state, the internal logic becomes abnormally bloated, even may be difficult to implement.

For a long time, the use of switch statements has been the only way to implement finite state machines, and even a complex software system such as compilers, most of which are directly implemented by this method. However, with the gradual deepening of the application of state machine, the state machine is more and more complex, this method also began to face a variety of severe tests, the most troubling is if the state machine state is very much, or the transition between States is unusually complex, A state machine that is constructed simply by using the switch statement will be non-maintainable.

Back to top of page

Iii. automatic generation of state machines

Writing a state machine for a practical software system is not a very easy task, especially when the state machine itself is more complex, and many programmers who have experienced similar experiences often describe it as "not creative" because they need to devote a lot of time and energy to managing state machines in various states, Rather than the running logic of the program itself. As a general software design mode, the state machine of various software systems will certainly have some common features, so people start to try to develop some tools to automatically generate the framework code of finite state machine, and there is a very good choice under Linux ──fsme (finite Machine Editor).

Figure 2 Visualization of the Fsme

Fsme is a QT-based finite state machine tool that allows the user to model the state machine required in a program graphically, and also automatically generates state machine framework code implemented in C + + or Python. The following is an example of the state machine of a gate in Figure 1, which shows how to use the state machine code required by the FSME to generate the program.

3.1 State Machine Modeling

First run the Fsme command to start the state machine Editor, and then click the "New" button on the toolbar to create a new state machine. There are five basic elements for building a state machine in Fsme: event, input, output, state, and transform (Transition), four of which can be found in the tree list on the left side of the interface.

    • State modeling Select the "states" item in the tree list to the left of the Fsme interface and press the INSERT key on the keyboard to insert a new state. Then enter the name of the state in the "Name" text box at the bottom right, and then click where you want to place the state in the drawing area at the top right, and a new state is created. In the same way you can add all the states required by the state machine, as shown in 3.                       Figure 3 State modeling
    • Event Modeling

      Select the "Events" item in the tree list to the left of the Fsme interface, then press the INSERT key on the keyboard to add a new event, then in the lower right Enter the name of the event in the "Name" text box, and then click the "Apply" button, and a new event is created. In the same way you can add all the events required by the state machine, as shown in 4.

      Figure 4 Event modeling
    • Transformation Modeling

      State transitions are the most important part of the entire modeling process, and it is used to define how one state in a finite state machine switches to another state. For example, when the state machine used to control the gate is in the opened state, if there is a close event, then the state machine's current state is switched to the closed state, so a complete process can be described in the state machine model with closedoor such a transformation.

      To add such a transformation in fsme, you first need to select the "opened" item under "states" in the tree list on the left side of the interface, then press the INSERT key on your keyboard to add a new transform, and then enter the name of the conversion in the "Name" text box in the lower-right corner. Closedoor ", enter" close "in the" Condition "text box to indicate that the condition that triggered the transition is the occurrence of event Close, and the" Closed "entry in the" Target "drop-down box indicates that the state machine will be switched to the Closed state after the conversion occurs. Finally click on the "Apply" button and a new state transition relationship is defined, as shown in 5. In the same way, you can add all the transformations required by the state machine.

      Figure 5 Transformation Modeling
3.2 Generating a state machine framework

Using Fsme not only enables visualization of state machine modeling, but more importantly it can also automatically generate a state machine framework that is implemented in C + + or Python based on the resulting model. First select "Root" in the tree list on the left side of the Fsme interface, then enter the state machine's name "DOORFSM" in the "Name" text box in the lower right corner, and then select "Opened" from the "Initial State" drop-down list as the state machine's initialization state, as shown in 6.

Figure 6 Setting the initial properties

After you save the state machine model as a DOOR.FSM file, use the following command to generate a header file that contains a state machine definition:

[Email protected] code]$ FSMC door.fsm-d-o DoorFSM.h

Further, you can generate framework code that includes a state machine implementation:

[Email protected] code]$ FSMC door.fsm-d-impl doorfsm.h-o DoorFSM.cpp

If you want to validate the generated state machine, you only need to manually write a piece of code for testing:

/  * * TestFSM.cpp * Test generated state machine framework */#include "DoorFSM.h" int main () {  DOORFSM door;  Door. A (doorfsm::close);  Door. A (doorfsm::lock);  Door. A (doorfsm::unlock);  Door. A (Doorfsm::open);}

Finite state machines are driven by events, and in the Fsme generated state machine framework code, method A () can be used to send corresponding events to the state machine, providing the "power" required for the state machine to function properly. The state machine is responsible for maintaining an event queue within it, and all incoming events are placed in the event queue for waiting, guaranteeing that they will be processed sequentially in the order in which they arrive. When dealing with each arriving event, the state machine checks to see if the transition condition corresponding to that state has been met, and activates the corresponding state transition process, depending on the state in which it is currently located.

Use the following command to compile the generated state machine framework and the test code into an executable file:

[Email protected] code]$ g++ DoorFSM.cpp testfsm.cpp-o FSM

Because the-D option was previously used to generate state machine code with the FSMC command, the resulting state machine framework contains some debugging information, including the activation event at each state transition in the state machine, the state before the transition, the transition experienced, the transformed state, and so on, as follows:

[Email protected] code]$/fsmdoorfsm:event: ' Close ' doorfsm:state: ' opened ' doorfsm:transition: ' Closedoor ' DOORFSM: New state: ' Closed ' doorfsm:event: ' Lock ' doorfsm:state: ' Closed ' doorfsm:transition: ' Lockdoor ' doorfsm:new state: ' Locked ' doorfsm:event: ' Unlock ' doorfsm:state: ' Locked ' doorfsm:transition: ' Unlockdoor ' doorfsm:new state: ' Unlocked ' Doorfsm:event: ' Open ' doorfsm:state: ' Unlocked ' doorfsm:transition: ' Opendoor ' doorfsm:new State: ' Opened '
3.3 Custom State machine

The current state machine has been able to respond to various events from outside, and appropriately adjust their current state, that is, the function of the state machine engine has been implemented, the next thing to do is to customize according to the specific needs of the application, the state machine to join the software system itself related to the processing logic. In Fsme, the operations associated with specific applications are called output, which are actually virtual functions that require a specific implementation by the user, and the automatically generated state machine engine is responsible for invoking them when entering or exiting a state.

Still in the case of the state machine that controls the gates, let's say we want to add some processing logic when we enter each state. First in the tree list on the left side of the Fsme interface, select the "Outputs" item, then press the INSERT key on the keyboard to add a new output, enter the name in the "Name" text box at the bottom right, and click the "Apply" button, and a new output is created, as shown in 7. You can add all the output required by the state machine in the same way.

Figure 7 Adding output

When all the outputs are defined, the corresponding output is then bound for each state in the state machine. First select the appropriate state in the "states" item on the left side of the Fsme interface, then select the output corresponding to that state from the Available list box in the lower-right corner, and then click the < button to add it to the "in" list, as shown in 8. The same way you can set the corresponding output for all States in the state machine, the same state can have multiple outputs, where the output in the in list is called when the state is entered, and the output in the out list is called when exiting the state. The order of the output calls is consistent with its order in the in or out list.

Figure 8 Setting output for status

Because of the modification of the state machine model, we need to generate the frame code of the state machine again, but this time we do not need to add the-D parameter:

[Email protected] code]$ FSMC door.fsm-o doorfsm.h[[email protected] code]$ FSMC door.fsm-d-impl doorfsm.h-o DOORFSM. Cpp

We have added Enteropend, enterclosed, enterlocked, and enterunlocked four outputs to the new state machine model, so there are a few pure virtual functions in the generated class DOORFSM:

      virtual void enteropened () = 0;   virtual void enterlocked () = 0;   virtual void enterunlocked () = 0;   virtual void enterclosed () = 0;

Obviously, at this point the generated state machine framework can no longer be compiled directly, we must derive a subclass from the class DOORFSM, and provide a concrete implementation of these pure virtual functions:

  /* * DoorFSMLogic.h * state Machine Control Logic header file */#include "DoorFSM.h" class Doorfsmlogic:public DOORFSM {  protected:  virtual void enteropened ();   virtual void enterlocked ();   virtual void enterunlocked ();   virtual void enterclosed (); };

As mentioned earlier, these functions actually represent the processing logic of the application system, as an example we simply output some hints:

/  * * DoorFSMLogic.cpp * Implementation file for state machine control logic */#include "DoorFSMLogic.h" #include <iostream>void doorfsmlogic:: Enteropened () {    std::cout << "Enter opened state." << Std::endl;} void doorfsmlogic::enterclosed () {    std::cout << "Enter Closed state." << Std::endl;} void doorfsmlogic::enterlocked () {    std::cout << "Enter Locked state." << Std::endl;} void doorfsmlogic::enterunlocked () {    std::cout << "Enter unlocked state." << Std::endl;}

Similarly, in order to validate a generated state machine, we also need to manually write a test code:

/  * * TestFSM.cpp * Test state machine logic */#include "DoorFSMLogic.h" int main () {  doorfsmlogic door;  Door. A (doorfsm::close);  Door. A (doorfsm::lock);  Door. A (doorfsm::unlock);  Door. A (Doorfsm::open);}

Use the following command to compile the generated state machine framework and the test code into an executable file:

[Email protected] code]$ g++ DoorFSM.cpp DoorFSMLogic.cpp testlogic.cpp-o logic

The results of the operation are as follows:

[Email protected] code]$/logicenter Closed state. Enter Locked State. Enter unlocked state. Enter opened state.

This article deals with code downloads: Code.zip

Back to top of page

Iv. Summary

In object-oriented software systems, some objects have very complex life cycle models, and the use of finite state machines is the best way to describe such objects. As a kind of software design mode, the concept of finite state machine is not complicated, it is not difficult to realize it, but the problem is that when the model of state machine is complex to a certain degree, it will bring difficulties in implementation and maintenance. Linux fsme is a visual finite state machine modeling tool, and supports the automatic generation of state machine framework code, which makes it easier to build application systems based on finite state machines.

"Reprint" http://www.ibm.com/developerworks/cn/linux/l-fsmachine/index.html

Constructing finite state machines for Linux applications

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.