SMC状态机 讲解2 从模型到SMC
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
// State
Idle
{// 转换到下一个状态的动作Run Running {}
}
状态和转换名称的命名规则必须为“[A- za -z_][A- za -z0-9_]*”形式。
3、外部环回转换 External Loopback Transition
// State
Idle
{// 转换到下一个状态的动作Timeout Idle {}
}
外部环回确实离开当前状态并返回到当前状态。这意味着执行状态的exit和entry操作。这与内部环回转换相反。
4、内部环回转换 Internal Loopback Transition
// 状态
Idle
{// 转换到下一个状态的动作Timeout nil {}
}
使用“nil”作为下一个状态将导致转换保持在当前状态,而不是离开它。这意味着状态的退出和进入操作不会被执行。这与外部环回转换相反。
5、转换动作
// 状态
Idle
{//转换Run// 下一个状态Running// 动作{StopTimer("Idle");DoWork();}
}
- 转换的动作必须包含在“{}”中。
- 动作的形式为“[A-Za-z] [A-Za-z0-9_ -] *()”。参数列表(argument list)必须为空或由逗号分隔的字面值组成。例如:整数(正数或负数、十进制、八进制或十六进制)、浮点数、双引号括起来的字符串、常量和转换参数。
- 操作必须是%class类中的成员函数,并且可以被状态机访问。通常这意味着c++中的公共成员函数或Java中的包。
动作参数包括:
4. 整数(例如1234)。
5. 浮点数(如12.34)。
6. 字符串(例如:“中的”)。
7. 一个转换参数。
8. 常量、#define或全局变量。
9. 独立的子程序或方法调用(例如event.getType())。
6、转换Guard
// State
Idle
{// TransRun// Guard condition[ctxt.isProcessorAvailable() == true &&ctxt.getConnection().isOpen() == true]// Next StateRunning// Actions{StopTimer("Idle");DoWork();}Run nil {RejectRequest();}
}
guard必须包含一个条件,该条件是有效的目标语言源代码——也就是说,它将是一个有效的“if”语句。定义的guard可能包含&&s、||s、比较运算符(==、<等)和嵌套表达式。SMC将您的保护条件逐字复制到生成的输出中。
如果guard条件的计算结果为true,则进行转换。如果gurad条件的计算结果为false,则发生以下情况之一(按优先级排序):
- 如果状态有另一个具有相同名称和参数的受保护转换,则检查该转换的保护。
- 否则,如果状态有另一个具有相同名称和参数列表的未保护转换,则进行该转换。
- 如果以上都不是,则遵循默认的转换逻辑。
一个状态可以有多个具有相同名称和参数列表的转换,只要它们都有唯一的gurad。当一个状态确实有多个具有相同名称的转换时,在排序它们时必须小心。状态机编译器将以与您使用的相同的从上到下的顺序检查转换,除了未保护的版本。只有当所有被保护的版本都失败时,才会采取这种做法。guard排序只有在guard不是互斥的情况下才重要,也就是说,对于同一个事件,多个gurad的值可能为true。
7、转换参数
// State
Idle
{// TransitionRun(msg: const Message&)// Guard condition[ctxt.isProcessorAvailable() == true &&msg.isValid() == true]// Next StateRunning// Actions{StopTimer("Idle");DoWork(msg);}Run(msg: const Message&)// Next State Actionsnil {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动作
当转换离开某个状态时,它会在任何转换操作之前执行该状态的退出操作。当转换进入某个状态时,它执行该状态的进入操作。转换按以下顺序执行操作:
- “From”状态的退出动作。
- 将当前状态设置为空。
- 转换操作的顺序与.sm文件中定义的顺序相同。
- 将当前状态设置为“to”状态。
- “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();}
}
这将导致状态机:
-
转换到 BlockPop 状态。
-
执行 BlockPop entry 动作。
-
Push到 WaitMap::Blocked 状态。
-
执行 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转换的不同之处在于:
- 未指定最终状态。这是因为pop转换将返回到发出相应推送的任何状态。
- 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会有两个独立的机制来处理这种情况。
- “Default”状态。每个%map都可以有一个名为“Default”的特殊状态(注意D为大写)。与所有其他状态一样,默认状态包含转换
Default
{//有效的运行请求,但转换在无效状态下发生。对有效消息发送拒绝回复。Run(msg: const Message&)[ctxt.isProcessorAvailable() == true &&msg.isValid() == true]nil{RejectRequest(msg);}// 在无效状态下接收到的无效消息将被忽略。Run(msg: const Message&)nil{}ShutdownShuttingDown{StartShutdown();}
}
默认状态转换可能具有非默认转换的保护和参数特性。这意味着对于同一转换,默认状态可能包含多个受保护和一个不受保护的定义。
- “默认”转换。它被放置在状态中,用于备份所有转换。
Connecting
{// 现在连接到远端,可以登录了。ConnectedConnected{logon();}// 此时的任何其他转换都是错误的。// 请停止连接进程,稍后重试。DefaultRetryConnection{stopConnecting();}
}
因为任何转换都可以通过默认转换,所以默认转换:
-
可能没有参数列表。
-
默认转换可能需要一个guard。
-
将Default转换置于Default状态意味着将处理所有转换。
相关文章:

SMC状态机 讲解2 从模型到SMC
SMC状态机 讲解2 从模型到SMC 1、实例化有限状态机(FSM)2、简单转换 Simple Transition3、外部环回转换 External Loopback Transition4、内部环回转换 Internal Loopback Transition5、转换动作6、转换Guard7、转换参数8、Entry 和 Exit动作9、Push 转换10、Pop转换…...

MyBatis-Plus的使用
MyBatis-Plus 1、mybatis-plus介绍 官网:https://baomidou.com/ MyBatis-Plus (简称 MP)是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。MyBatis-Plus提供了通用的mapper…...

板卡设计+硬件每日学习十个知识点(44)23.8.24 (检测单元设计,接口部分设计,板卡电源输入设计,电源检测电路)
文章目录 1.检测单元介绍(使用GD32单片机)2.GD32的最小系统板3.GD32的温度监测4.GD32的电压监测和电流监测5.GD32的布线6.接口部分设计7.板卡电源输入设计8.电源检测电路 1.检测单元介绍(使用GD32单片机) 答: 首先要为…...

jmeter HTTP信息头管理器
首先,打开JMeter并创建一个新的测试计划。右键单击测试计划,选择"添加" > “线程组”,然后在线程组上右键单击,选择"添加" > “Sampler” > “HTTP请求”。 在HTTP请求中填写服务器的URL和其他必要…...
各种中间件的默认端口
面试时会忘记个别中间件端口 docker:2375 nacos:8848 redis:6379 rabbitMq: 5672(后台配置的端口)15672(web管理界面)账号:guest15674(web STOMP插件):通过WebSocket…...

leetcode303. 区域和检索 - 数组不可变(java)
前缀和数组的应用 区域和检索 - 数组不可变题目描述前缀和数组代码演示 区域和检索 - 数组不可变 难度 - 简单 原题链接 - 区域和检索 - 数组不可变 题目描述 给定一个整数数组 nums,处理以下类型的多个查询: 计算索引 left 和 right (包含 left 和 righ…...

PHP 安装Composer,vue前端依赖包
电脑安装Composer 官网下载:https://getcomposer.org/Composer-Setup.exe 后端安装: 检查是否安装依赖: 安装Composer install 或 Composer i 前端安装: yarn install 安装依赖...

OpenCV项目开发实战--基于Python/C++实现鼠标注释图像和轨迹栏来控制图像大小
鼠标指针是图形用户界面 (GUI) 中的关键组件。没有它,您就无法真正考虑与 GUI 进行交互。那么,让我们深入了解 OpenCV 中鼠标和轨迹栏的内置函数。我们将演示如何使用鼠标来注释图像,以及如何使用轨迹栏来控制图像的大小 我们将使用下图来演示 OpenCV 中鼠标指针和轨迹栏功能…...
❤ Vue使用Eslint检测报错问题和解决
❤ Vue使用Eslint检测报错问题和解决 1、 关闭Eslint检测 关闭ESLint语法检测即可:具体步骤如下: 第一步我们打开setting设置: 打开左上角的file,然后点击setting 接下来进入setting以后我们来看下面操作: eol-l…...

解决运行在微信小程序中报[ app.json 文件内容错误] app.json: app.json 未找到(env: Windows,mp,1.05.2204
找到project.config.json文件夹 添加 "miniprogramRoot": "unpackage/dist/dev/mp-weixin/", 即可...
python 基础 -- 安装Python模块
作为一个流行的开源开发项目,Python拥有一个由贡献者和用户组成的活跃支持社区,他们还根据开源许可条款向其他Python开发人员提供他们的软件。 这允许Python用户有效地共享和协作,从其他人已经创建的常见(有时甚至是罕见的!)问题的解决方案中…...

C语言实现状态机
关于状态机,基础的知识点可以自行理解,讲解的很多,这里主要是想写一个有限状态机FSM通用的写法,目的在于更好理解,移植,节省代码阅读与调试时间,体现出编程之美。 传统的实现方案 if...else : …...
交叉编译工具链arm-linux-gnueabihf的安装-ubuntu 20.04
前面下载安装步骤参考该博主的文章 http://t.csdn.cn/ZbjFX 另:本人对所遇到的环境变量的配置问题作补充 1.修改环境变量 建议直接在.bashrc文件作修改 ,修改方式相同 ( vi :视自己的编辑器而定) sudo vi ~/.bashrc 2.修改环境变量后,可…...
Java的类加载器
类加载 1、ClassLoader 用来加载 Class 文件 2、 系统内置的ClassLoader 通过双亲委托加载指定目录下的class和资源 3、 可以自定义ClassLoader 一般覆盖findClass() 4、ContextClassLoader 与线程相关,可以获取和设置,可以绕过双亲委托的机制。 三个类…...

Stable Diffusion web UI 部署详细教程
前言 本文使用 AutoDL 平台进行 Stable Diffusion web UI 云端部署 AutoDL 官网:AutoDL算力云 | 弹性、好用、省钱。租GPU就上AutoDL Stable Diffusion web UI 官网:AUTOMATIC1111/stable-diffusion-webui: Stable Diffusion web UI (github.com) 步…...

《深度学习计算机视觉 》书籍分享(包邮送书三本)
深度学习计算机视觉介绍 随着计算机技术的发展和进步,计算机视觉领域得到了广泛的关注和研究。而深度学习作为一种强大的机器学习方法,已经成为计算机视觉领域的重要工具之一。本文将介绍深度学习在计算机视觉中的应用和取得的成果。 深度学习是一种模…...

【使用 k 折叠交叉验证的卷积神经网络(CNN)】基于卷积神经网络的无特征EMG模式识别研究(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

微服务 Nacos配置热部署
在nacos中添加配置文件 在配置列表中添加配置, 注意:项目的核心配置,需要热更新的配置才有放到nacos管理的必要。基本不会变更的一些配置还是保存在微服务本地比较好。 从微服务拉取配置 微服务要拉取nacos中管理的配置,并且与…...

国产调度器之光——Fsched到底有多能打?
这是一篇推荐我们速石自研调度器——Fsched的文章。 看起来在专门写调度器,但又不完全在写。 往下看,你就懂了。 本篇一共五个章节: 一、介绍一下主角——速石自研调度器Fsched 二、只要有个调度器,就够了吗? 三…...
LeetCode:53. 最大子数组和 - Python
53. 最大子数组和 问题描述: 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。 示例 1: 输入:nums [-…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
Admin.Net中的消息通信SignalR解释
定义集线器接口 IOnlineUserHub public interface IOnlineUserHub {/// 在线用户列表Task OnlineUserList(OnlineUserList context);/// 强制下线Task ForceOffline(object context);/// 发布站内消息Task PublicNotice(SysNotice context);/// 接收消息Task ReceiveMessage(…...

centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...

Ascend NPU上适配Step-Audio模型
1 概述 1.1 简述 Step-Audio 是业界首个集语音理解与生成控制一体化的产品级开源实时语音对话系统,支持多语言对话(如 中文,英文,日语),语音情感(如 开心,悲伤)&#x…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
AspectJ 在 Android 中的完整使用指南
一、环境配置(Gradle 7.0 适配) 1. 项目级 build.gradle // 注意:沪江插件已停更,推荐官方兼容方案 buildscript {dependencies {classpath org.aspectj:aspectjtools:1.9.9.1 // AspectJ 工具} } 2. 模块级 build.gradle plu…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...