一乐电子

 找回密码
 请使用微信账号登录和注册会员

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3643|回复: 0

[操作系统]QEP之init()和dispatch()流程图

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑 ( u4 t! a% C8 [) o5 I- W  O

# }" u) g+ y' L$ _; BQEP之init()和dispatch()流程图' j5 |: i( [* c8 c+ P6 P
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。

* X9 c' ]: P( ?5 p+ \( O     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。

* I1 J, l4 q) J# s, ]: Z8 ytypedef uint8_t QState;                           

3 H# }  P$ n& P, w" k2 H0 S! ]6 ]
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/
8 G0 g$ }5 l# V0 ^, V1 `& p) Y, k5 f
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   

% R5 B3 a1 e5 g. s& u$ R+ q! p0 IQStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/3 r. ~* `! X5 U5 T4 I; ^
} QFsm;6 B' R7 A0 q; X4 s% C
* k; `5 P4 h- d; e# K: @
typedef struct QFsmTag QHsm;! K8 w( J3 D$ B" T  O$ r
# }* `7 O+ r7 ^* T0 L" d
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */
- {" R0 l( r! j+ e2 j+ Z" t6 t
#define Q_IGNORED()         (Q_RET_IGNORED)+ N- r; ?3 v9 r1 r# g, a' |# @+ @
/* 已处理事件 */9 D5 U, N% n: j+ q
#define Q_HANDLED()         (Q_RET_HANDLED)5 U3 s, ?" |& K& ^; N
/* 状态转移 */
& x3 Y" M" Z7 @#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)
2 S/ P" |6 T# |/* 到超状态 */
9 u4 M4 D/ A* \' m9 T#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER): d4 z7 _+ {/ l$ x9 H+ S1 Q
: P5 [1 F- q5 [
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */

  T' S- Z/ g6 H. I% W! P  s/ r. I#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))5 H8 {: V- e! _2 i7 r  s
/* 触发退出动作,在层次状态机HSM */
+ A2 {! ?( D% R+ V- f- f#define QEP_EXIT_(state_)     6 l% ]4 {3 W3 v) M% {) e1 E
if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED)
. j2 s+ I% J5 X7 q7 }* r1 g{& r0 B9 t1 ^! a; W1 z0 D4 P) ~
         ...QS     % b" P/ \- |2 T: n" k/ ~$ Z, L
}
* v1 ^% ]! L% U  _0 S" R$ Z' Y1 a
$ b. u- B- T% h9 A; a
/* 触发进入动作,在层次状态机HSM */
8 j- T# j; Z' t- o+ D#define QEP_ENTER_(state_)     
8 P" U! c$ d5 l( V! X# |if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) 9 k5 c! t% s0 z5 v3 i4 ^
{
1 }" u5 d% O+ f5 k" I5 v1 {         ...QS     
! X" y& M' v& N}
* D) w& J) X4 Z' ^* I2 k/ L9 e0 a$ [9 {$ z/ ?: Z& O% Y, X
/ K3 O* g/ ^, ~9 n' k# y: B$ ]3 t
/* 触发空动作,在层次状态机HSM (自加)*/
: S8 K7 H5 w5 S. G#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  ( H) Q8 M& l# i  e3 q. b5 S
7 k. Z, a. }4 `
2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程- A1 A& J" E8 n2 M0 @
815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程
$ F' i0 h0 _9 M3 X4 f' M- _: Q) B  f 815490-20151227210907999-1694829155.png 

   图3.QFsm_dispatch()流程3.Hsm状态机init()和dispatch()流程

从顶级状态的初始伪状态开始,到本初始伪状态转换的终状态(子状态),执行进入动作。在终状态(子状态)继续检查有没有子初始伪状态,如果有的话,继续进入,执行进入动作,直到最终状态。

(1)QHsm_init()流程# M3 J7 }- l# x- n
815490-20151227210908374-1012628730.png 

   图4.QHsm_init()流程图与层次状态机

(2)QHsm_dispatch()流程
2 c3 M% w- R7 s 815490-20151227210910999-1369603859.png 

   图5.QHsm_dispatch()流程图
815490-20151227210908343-159821549.png
815490-20151227210907906-1888535234.png
815490-20151227210907999-1694829155.png
815490-20151227210908374-1012628730.png
815490-20151227210910999-1369603859.png

本版积分规则

QQ|一淘宝店|手机版|商店|一乐电子 ( 粤ICP备09076165号 ) 公安备案粤公网安备 44522102000183号

GMT+8, 2025-10-28 14:27 , Processed in 0.033055 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表