【无标题】

Hierarchical State Machine

In this article, we will be highlighting the advantages of hierarchical state machine design over conventional state machine design.

In conventional state machine design, all states are considered at the same level. The design does not capture the commonality that exists among states. In real life, many states handle most messages in similar fashion and differ only in handling of few key messages. Even when the actual handling differs, there is still some commonality. Hierarchical state machine design captures the commonality by organizing the states as a hierarchy. The states at the higher level in hierarchy perform the common message handling, while the lower level states inherit the commonality from higher level ones and perform the state specific functions. The table given below shows the mapping between conventional states and their hierarchical counterparts for a typical call state machine.

|----------------------|--------------------------------------------------|
| Conventional States | Hierarchical States |
| Awaiting First Digit | Setup.CollectingDigits.AwaitingFirstDigit |
| Collecting Digits | Setup.CollectingDigits.AwaitingSubsequent Digits |
| Routing Call | Setup.RoutingCall |
| Switching Path | Setup.SwitchingPath |
| Conversation | Conversation |
| Awaiting Onhook | Releasing.AwaitingOnhook |
| Releasing Path | Releasing.ReleasingPath |

A conventional state machine is designed as a two dimensional array with one dimension as the state and the other dimension specifying the message to be handled. The state machine determines the message handler to be called by indexing with the current state and the received message. In real life scenario, a task usually has a number of states along with many different types of input messages. This leads to a message handler code explosion. Also, a huge two dimensional array needs to be maintained. Hierarchical state machine design avoids this problem by recognizing that most states differ in the handling of only a few messages. When a new hierarchical state is defined, only the state specific handlers need to be specified.

Conventional State Machine Example

The figure below describes the state transition diagram for an active standby pair. The design here assumes that the active and standby are being managed by an external entity.

The different states for the state machine are Active, Standby, Suspect and Failed. The input messages to be handled are Switchover, Fault Trigger, Diagnostics Passed, Diagnostics Failed and Operator Inservice. Thus the handler two dimensional array is 4 x 5 i.e. 20 handlers need to be managed.

The code below shows the handlers that need to be defined. A dummy "do nothing" handler should be specified for all other entries of the two dimensional state table. This simple example clearly illustrates the problem with conventional state design. There is a lot of code repetition between handlers. This creates a maintenance headache for state machine designers. We will see in the following section that hierarchical state machine design exploits these very similarities to implement a more elegant state structure.

Conventional State Machine Implementation

Hierarchical State Machine Example

The following state transition diagram recasts the state machine by introducing two levels in the hierarchy. Inservice and Out_Of_Service are the high level states that capture the common message handling. Active and Standby states are low level states inheriting from Inservice state. Suspect and Failed are low level states inheriting from Out_Of_Service state.

The following diagram clearly illustrates the state hierarchy. Even the Inservice and Out_Of_Service, high level states inherit from the Unit_State that is at the highest level.

Hierarchical State Machine Source Code

The C++ implementation details of the hierarchical state machine are given below. It is apparent that all the commonality has moved to the high level states viz. Inservice and Out_Of_Service. Also, contrast this with the conventional state machine implementation.

The code below contains hyperlinks to more detailed information about the classes, methods and variables in this information.

Header File

The header file below declares the Unit state machine using the Hierarchical_State_Machine class. Important points to note are:

  • The state classes are nested private classes within the state machine class. Thus they are not visible to other classes.
  • The state machine declares all states to be friend classes. This does not break the encapsulation as only a private class is being declared as a friend.
  • The base class (Unit_State) provides a "do nothing" implementation for all handlers. Thus an inheriting state has to provide an implementation only for that methods it supports.
  • State objects are declared static. Thus multiple instances of the state machine will share the same state objects. Due to this, the Hierarchical_State_Machine class has a small memory footprint.
  • Only the main message handler, On_Message, is declared public. All helper functions are private.
  • A pointer to the current state is maintained in p_Current_State variable. This variable gets initialized using the Next_State method.
Hierarchical_State_Machine.h

Source File

Important things to note about the source file:

  • On_Message, the main message handler invokes the appropriate handler based on the type of the message. The message is passed to the current state object.
  • The Out_Of_Service and Inservice base states handle most of the message processing. In some cases, the inheriting states perform some additional action and call the handler for the base state for the common part of the handling.
Hierarchical_State_Machine.cpp
相关推荐
alexhilton11 小时前
Room Fts4:全文搜索替代 SQL LIKE
android·kotlin·android jetpack
hai_android16 小时前
把 Android App 打包成系统应用(System App)
android·kotlin·android jetpack
JMchen17 小时前
【Jetpack 内核实战 01】开篇:Jetpack 组件全家桶核心逻辑与专栏完整规划
android·kotlin·android jetpack
骑着蜗牛撵大象32719 小时前
Linux 进程间通信之管道:从 pipe() 的内核语义到 FIFO 落地排错
android·java·linux·系统编程·fifo·管道·进程间通信
hunterandroid19 小时前
Retrofit 网络请求的异常处理与重试策略实战
android
sejinan19 小时前
极致轻量与秒级起播:NativeWasmTv 开源硬核技术解析与升级版体验
android·开源·webview·tv
小羊没烦恼!20 小时前
Ajax与JSON的一些总结
android·java·前端·数据库·mysql·算法·okhttp
黄俊懿20 小时前
【架构师从入门到进阶】第六章:服务集群优化——第八节:线程数公式
java·服务器·数据库·分布式·性能优化·架构·系统架构
mmsx20 小时前
Android 静默失败实录:五个没有日志的线上事故
android·kotlin
hai_android21 小时前
从零实现一个支持跨进程(IPC)的自定义 Toast
android·kotlin·android jetpack