SMC状态机 讲解2 从模型到SMC

news2025/1/19 8:26:48

SMC状态机 讲解2 从模型到SMC

  • 1、实例化有限状态机(FSM)
  • 2、简单转换 Simple Transition
  • 3、外部环回转换 External Loopback Transition
  • 4、内部环回转换 Internal Loopback Transition
  • 5、转换动作
  • 6、转换Guard
  • 7、转换参数
  • 8、Entry 和 Exit动作
  • 9、Push 转换
  • 10、Pop转换
  • 11、默认转换

1、实例化有限状态机(FSM)

private final AppClassContext _fsm;

public AppClass()
{
    // 初始化应用程序类
    // 实例化有限状态机
    // 注意:传递给FSM是安全的
    // 构造函数,因为只有FSM的构造函数
    // 将其存储在数据成员中
    _fsm = new AppClassContext(this);
}

// 实例化后输入FSM启动状态
// 应用对象
public void startWorking()
{
    _fsm.enterStartState();
    return;
}

2、简单转换 Simple Transition

Simple Transition

// State
Idle
{
    // 转换到下一个状态的动作
    Run        Running        {}
}

状态和转换名称的命名规则必须为“[A- za -z_][A- za -z0-9_]*”形式。

3、外部环回转换 External Loopback Transition

在这里插入图片描述

// State
Idle
{
    // 转换到下一个状态的动作
    Timeout    Idle           {}
}

外部环回确实离开当前状态并返回到当前状态。这意味着执行状态的exitentry操作。这与内部环回转换相反。

4、内部环回转换 Internal Loopback Transition

在这里插入图片描述

// 状态
Idle
{
    // 转换到下一个状态的动作
    Timeout    nil            {}
}

使用“nil”作为下一个状态将导致转换保持在当前状态,而不是离开它。这意味着状态的退出和进入操作不会被执行。这与外部环回转换相反。

5、转换动作

在这里插入图片描述

// 状态
Idle
{
    //转换
    Run
        // 下一个状态
        Running
        // 动作
        {
            StopTimer("Idle");
            DoWork();
        }
}
  1. 转换的动作必须包含在“{}”中。
  2. 动作的形式为“[A-Za-z] [A-Za-z0-9_ -] *()”。参数列表(argument list)必须为空或由逗号分隔的字面值组成。例如:整数(正数或负数、十进制、八进制或十六进制)、浮点数、双引号括起来的字符串、常量和转换参数。
  3. 操作必须是%class类中的成员函数,并且可以被状态机访问。通常这意味着c++中的公共成员函数或Java中的包。

动作参数包括:
4. 整数(例如1234)。
5. 浮点数(如12.34)。
6. 字符串(例如:“中的”)。
7. 一个转换参数。
8. 常量、#define或全局变量。
9. 独立的子程序或方法调用(例如event.getType())。

6、转换Guard

在这里插入图片描述

// State
Idle
{
    // Trans
    Run
      // Guard condition
      [ctxt.isProcessorAvailable() == true &&
       ctxt.getConnection().isOpen() == true]
       
        // Next State
        Running
        // Actions
        {
            StopTimer("Idle");
            DoWork();
        }

    Run nil {RejectRequest();}
}

guard必须包含一个条件,该条件是有效的目标语言源代码——也就是说,它将是一个有效的“if”语句。定义的guard可能包含&&s、||s、比较运算符(==、<等)和嵌套表达式。SMC将您的保护条件逐字复制到生成的输出中。

如果guard条件的计算结果为true,则进行转换。如果gurad条件的计算结果为false,则发生以下情况之一(按优先级排序):

  1. 如果状态有另一个具有相同名称和参数的受保护转换,则检查该转换的保护。
  2. 否则,如果状态有另一个具有相同名称和参数列表的未保护转换,则进行该转换。
  3. 如果以上都不是,则遵循默认的转换逻辑。

一个状态可以有多个具有相同名称和参数列表的转换,只要它们都有唯一的gurad。当一个状态确实有多个具有相同名称的转换时,在排序它们时必须小心。状态机编译器将以与您使用的相同的从上到下的顺序检查转换,除了未保护的版本。只有当所有被保护的版本都失败时,才会采取这种做法。guard排序只有在guard不是互斥的情况下才重要,也就是说,对于同一个事件,多个gurad的值可能为true。

7、转换参数

在这里插入图片描述

// State
Idle
{
    // Transition
    Run(msg: const Message&)

      // Guard condition
      [ctxt.isProcessorAvailable() == true &&
       msg.isValid() == true]

        // Next State
        Running
        // Actions
        {
            StopTimer("Idle");
            DoWork(msg);
        }

    Run(msg: const Message&)
        // Next State    Actions
        nil              {RejectRequest(msg);}
}

Note:当使用转换guard和转换参数时,同一转换的多个实例必须具有相同的参数列表。就像c++和Java方法一样,Run(msg: const Message&)和Run()不是同一个转换。在使用多个gurad定义相同的转换时,如果不能使用相同的参数列表,将导致生成不正确的代码。

Tcl “arguments”:
虽然Tcl是一种无类型语言,但Tcl区分了按值调用和按引用调用。默认情况下,如果转换参数没有指定类型,SMC将生成按值调用的Tcl代码。但可以使用"value"或"reference"这些人为类型。

如果你的Tcl-targeted FSM有一个转换:

DoWork(task: value)
    Working
    {
        workOn(task);
    }

则生成的Tcl为:

public method DoWork {task} {
    workOn $this $task;
}

如果你的Tcl-targeted FSM有一个转换:

DoWork(task: reference)
    Working
    {
        workOn(task);
    }

则生成的Tcl为:

public method DoWork {task} {
    workOn $this task;
}

8、Entry 和 Exit动作

在这里插入图片描述

当转换离开某个状态时,它会在任何转换操作之前执行该状态的退出操作。当转换进入某个状态时,它执行该状态的进入操作。转换按以下顺序执行操作:

  1. “From”状态的退出动作。
  2. 将当前状态设置为空。
  3. 转换操作的顺序与.sm文件中定义的顺序相同。
  4. 将当前状态设置为“to”状态。
  5. “To”状态的进入动作。
// 状态
Idle //闲置
Entry {StartTimer("Idle", 1); CheckQueue();}//进入该状态时,执行该操作
Exit {StopTimer("Idle");} //离开该状态时,执行该操作
{
    //转换操作
}

从6.0.0版本开始,SMC生成一个enterStartState方法,该方法执行开始状态的进入动作。现在由应用程序在实例化有限状态机后调用start方法。如果不适合在启动时执行入口操作,则不要调用enterStartState。无需调用此方法来设置有限状态机的启动状态,这在FSM实例化时完成。此方法仅用于执行启动状态的进入操作。

如果要调用此方法,请确保在上下文类的构造函数之外调用。这是因为entry调用类方法。如果在上下文类的构造函数中调用enterStateState,则上下文实例将在完成初始化之前被引用,这是一件不好的事情。

enterStartState不防止被多次调用。它应该最多调用一次,并且在发出任何转换之前调用。不遵循这一要求可能会导致不适当的有限状态机行为。

是否执行状态的Entry和Exit操作取决于所采取的转换类型。下表显示了哪些转换执行“from”状态的Exit动作,哪些转换执行“to”状态的Entry动作。

转换类型执行“From”状态的Exit动作?执行“To状态的”Entry动作?
Simple Transition
External Loopback Transition
Internal Loopback Transition
Push 转换
Pop 转换

9、Push 转换

在这里插入图片描述

// SMC v1.3.2版本语法
Running
{
    Blocked    BlockPop/push(WaitMap::Blocked)  {GetResource();}
}

这将导致状态机:

  1. 转换到 BlockPop 状态。

  2. 执行 BlockPop entry 动作。

  3. PushWaitMap::Blocked 状态。

  4. 执行 WaitMap::Blocked entry 动作。

当WaitMap发出pop转换时,控制权将返回到BlockPop,并且从这里发出pop转换。

当一个状态有两个不同的转换,这两个转换推送到相同的状态,但需要以不同的方式处理弹出转换时,使用这个新语法。例如:

Idle
{
    NewTask     NewTask/push(DoTask)    {}
    RestartTask OldTask/push(DoTask)    {}
}

NewTask
{
    TaskDone    Idle                    {}
    // Try running the task one more time.
    TaskFailed  OldTask/push(DoTask)    {}
}

OldTask
{
    TaskDone    Idle                    {}
    TaskFailed  Idle                    {logFailure();}
}

10、Pop转换

在这里插入图片描述

pop转换与push转换的不同之处在于:

  1. 未指定最终状态。这是因为pop转换将返回到发出相应推送的任何状态。
  2. pop转换有一个可选参数:转换名称 transition name。

在上面的例子中,如果资源请求被授予,则状态机返回到执行推送的相应状态,然后进行该状态的OK转换。如果请求被拒绝,除了采取FAILED转换外,还会发生相同的事情。对应的push转换代码为:

Running
{
    Blocked    push(WaitMap::Blocked)    {GetResource();}
    
    // Handle the return "transitions" from WaitMap.
    OK   nil   {}
    FAILED     Idle   {Abend(INSUFFICIENT_RESOURCES);}
}

从SMC v. 1.2.0开始,可以在pop转换的transition参数之后添加其他参数。这些附加参数与传递给操作的其他参数一样,将被传递到命名转换中。按照上面的例子,给定pop转换pop(FAILED, errorCode, reason),那么FAILED应该被编码为:

FAILED(errorCode: ErrorCode, reason: string)
    Idle
    {
        Abend(errorCode, reason);
    }

11、默认转换

如果一个状态接收到一个在该状态中没有定义的转换,SMC会有两个独立的机制来处理这种情况。

  1. “Default”状态。每个%map都可以有一个名为“Default”的特殊状态(注意D为大写)。与所有其他状态一样,默认状态包含转换
Default
{
    //有效的运行请求,但转换在无效状态下发生。对有效消息发送拒绝回复。
    Run(msg: const Message&)
      [ctxt.isProcessorAvailable() == true &&
       msg.isValid() == true]
        nil
        {
            RejectRequest(msg);
        }

    // 在无效状态下接收到的无效消息将被忽略。
    Run(msg: const Message&)
        nil
        {}

    Shutdown
        ShuttingDown
        {
            StartShutdown();
        }
}

默认状态转换可能具有非默认转换的保护和参数特性。这意味着对于同一转换,默认状态可能包含多个受保护和一个不受保护的定义。

  1. “默认”转换。它被放置在状态中,用于备份所有转换。
Connecting
{
    // 现在连接到远端,可以登录了。
    Connected
        Connected
        {
            logon();
        }

    // 此时的任何其他转换都是错误的。
    // 请停止连接进程,稍后重试。
    Default
        RetryConnection
        {
            stopConnecting();
        }
}

因为任何转换都可以通过默认转换,所以默认转换:

  1. 可能没有参数列表。

  2. 默认转换可能需要一个guard。

  3. 将Default转换置于Default状态意味着将处理所有转换。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/925969.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI加持,创意设计效率百倍提升,探秘背后的数字化魔法

在当今创新潮流不断涌现的时代&#xff0c;人工智能正以惊人的速度和深度赋能各行各业&#xff0c;食品包装设计界也已来到了一个“拼创意、拼二创和拼审美”的时代。有了AI的加入&#xff0c;设计界正迎来一股AI创意风暴&#xff0c;不仅颠覆了设计流程&#xff0c;更为食品包…

机器学习教程(非常详细)从零基础入门到精通,看完这一篇就够了

一、机器学习的定义 从广义上来说&#xff0c;机器学习是一种能够赋予机器学习的能力以此让它完成直接编程无法完成的功能的方法。但从实践的意义上来说&#xff0c;机器学习是一种通过利用数据&#xff0c;训练出模型&#xff0c;然后使用模型预测的一种方法。 “训练”与“…

在leangoo免费敏捷工具中如何批量设置成员权限

Leangoo领歌是一款永久免费的专业敏捷开发管理工具&#xff0c;提供端到端敏捷研发管理解决方案&#xff0c;涵盖敏捷需求管理、任务协同、进展跟踪、缺陷管理、统计度量等。 包括小型团队敏捷开发&#xff0c;规模化敏捷SAFe&#xff0c;Scrum of Scrums大规模敏捷。其功能/解…

java包的package-info.java文件

Java包的下面可以放一个package-info.java文件&#xff0c;在这个文件中声明包&#xff0c;在注释中增加包的介绍信息。这样javadoc工具就可以优先从这个文件中获取包的介绍信息。 例如Java工程&#xff0c;在包com.thb下面有package-info.java文件&#xff1a; package-inf…

优秀产品奖!移远5G RedCap模组,让5G真正“轻”下来

8月24日&#xff0c;在通信世界全媒体主办的“5G RedCap技术与物联网应用创新研讨会”上&#xff0c;“5G RedCap优秀产品和解决方案”获奖名单发布&#xff0c;移远通信5G RedCap模组Rx255C系列以其在创新性、实用性、经济性、成熟性等方面的综合领先优势&#xff0c;获此殊荣…

Spring Boot进阶(58):集成PostgreSQL数据库及实战使用 | 万字长文,超级详细

1. 前言&#x1f525; PostgreSQL是一种广泛使用的开源关系型数据库&#xff0c;具有可靠性高、性能优异、拥有丰富的数据类型和扩展等优点&#xff0c;越来越多的企业和开发者开始使用它来存储和管理数据。而Spring Boot是一种快速开发的框架&#xff0c;可以简化开发过程并提…

照片怎么转换成pdf?几种照片转pdf方法看一看

照片怎么转换成pdf&#xff1f;照片转换成PDF是一个非常有用的技能&#xff0c;可以将多张照片合并为一个文件&#xff0c;方便保存和分享。现在也有很多方法可以将照片转换为PDF&#xff0c;下面就给大家介绍几种转换方法。 转换方法一&#xff1a;迅捷PDF转换器 这是一款功能…

GPT---1234

GPT:《Improving Language Understanding by Generative Pre-Training》 下载地址:https://cdn.openai.com/research-covers/language-unsupervised/language_understanding_paper.pdfhttps://cdn.openai.com/research-covers/language-unsupervised/language_understa…

前端遇到困扰怎么办?10年前端在线帮您解决问题,只需一杯下午茶

前端遇到困扰怎么办&#xff1f;10年前端在线帮您解决问题&#xff0c;只需一杯下午茶

Ceph入门到精通-基于ECMP的多活负载均衡策略

本文简单介绍一下&#xff0c;如何基于ECMP&#xff0c;使用QuaggaLVSKeepalived构建多活负载均衡方案 1. 背景介绍 负载均衡&#xff0c;主要用于大规模分布式集群下&#xff0c;提供高性能服务。为了给负载均衡器提供高可用&#xff0c;一般利用主备或者主主模式实现。主备模…

前端三剑客入门一文解决

文章目录 HTML快速开发网站Flask页面结构标签基础标签超链接图片列表下拉框表格input系列多行文本form表单 网络请求HTML案例 CSSCSS盒模型CSS样式定义CSS选择器 CSS样式使用1. 在标签上直接写2. 在head标签中写3.写到css文件中 标签样式1. 高度和宽度2. 块级和行内标签3.字体设…

原生微信小程序使用 wxs;微信小程序使用 vant-weapp组件

1.原生微信小程序使用 wxs 1.内嵌 WXS 脚本 2. 定义外链 wxs 3. 使用外连wxs 在这里插入图片描述 2. 微信小程序使用 vant weapp 1.安装步骤 2. 安装包管理(package.json)文件的方法 操作顺序 &#xff1a;文档地址 如果使用 typescript 需要操作步骤3&#xff0c;否则不…

go语言kafka入门

消息队列&#xff1a;一种基于异步通信的解耦机制&#xff0c;用于在应用程序或系统组件之间传递消息和数据 消息队列相关概念&#xff1a; 生产者&#xff08;Producer&#xff09;&#xff1a;生成并发送消息到消息队列中的应用程序或系统组件。 消费者&#xff08;Consumer&…

Node基础--WebStorm整合Node

通过上面的课程,我们对Node有了一个初步的体验,下面我们就把Node和开发工具WebStrom进行整合。 1.安装开发工具WebStrom (1).查找官方下载地址: https://www.jetbrains.com/webstorm/ (2).下载之后开始点击安装 (3).设置安装路径。注意:安装路径自定义 (4).按照自己的…

vue 简单实验 自定义组件 独立模块

1.概要 2.代码 2.1 const Counter {data() {return {counter: 0}},template:<div>Counter: {{ counter }}</div> }export default Counter 2.2 import Counter from ./t2.jsconst app Vue.createApp({components: {component-a: Counter} })app.mount(#count…

C - 滑动窗口 /【模板】单调队列

Description 有一个长为 n 的序列 a&#xff0c;以及一个大小为 k 的窗口。现在这个从左边开始向右滑动&#xff0c;每次滑动一个单位&#xff0c;求出每次滑动后窗口中的最大值和最小值。 例如&#xff1a; The array is [1,3,−1,−3,5,3,6,7] and k3。 Input 输入一共有…

ssm农产品仓库管理系统系统源码和论文

ssm农产品仓库管理系统系统源码和论文064 开发工具&#xff1a;idea 数据库mysql5.7 数据库链接工具&#xff1a;navcat,小海豚等 技术&#xff1a;ssm 选题的背景 中国是一个农产品生产的大国&#xff0c;可利用的农产品资源相对贫乏&#xff0c;传统的单纯依靠大量物质…

k3s or RKE2 helm安装报错dial tcp 127.0.0.1:8080: connect: connection refused

1.报错&#xff1a; Error: INSTALLATION FAILED: Kubernetes cluster unreachable: Get "http://127.0.0.1:8080/version": dial tcp 127.0.0.1:8080: connect: connection refused 2.问题原因&#xff1a; 1.因为helm默认使用k8s的配置文件&#xff0c;默…

华为云服务器如何安装多个数据库

由于我的项目对数据库版本有限制&#xff0c;需要在先前安装5.7的基础上再安装一个8.0.28版本的数据库。 安装5.7版本数据库的过程&#xff1a;华为云服务器部署mysql_瓜是西瓜的瓜的博客-CSDN博客 1、安装前准备 服务器版本&#xff1a;CentOS 7 将/etc/selinux/config里的…

最新Rimini主题 1.3.0 资源付费WordPress主题下载

RiMini主题介绍&#xff0c;支持微信&#xff0c;支付宝官方支付接口&#xff0c;个人PAYJS&#xff0c;虎皮椒&#xff0c;码支付&#xff0c;免登录购买&#xff0c;会员中心&#xff0c;支付齐全&#xff0c;体验超速&#xff0c;简单粗暴&#xff0c;支付接口齐全&#xff…