一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3770|回复: 0

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

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑
9 K' b* C* E" e: P- T- g5 M7 W# \% J5 P% C
QEP之init()和dispatch()流程图
1 A* P7 e3 F) f5 e
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。
9 w( V: g! }8 i/ [2 \- e6 Q
     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。

* b+ `7 F- g3 N9 Y( O  N9 V5 Jtypedef uint8_t QState;                           
" A4 v9 d; o1 V. g1 `4 C
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/
6 C! r: O( [9 z) C5 [1 N
& Q1 w% z& u- X  m
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   
2 b: a" D* H! i# L; f
QStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/
  K: w- n! B  `. Q0 \: Z} QFsm;
1 \* c% R) }1 j2 u* j" k% e/ H3 ^
4 ~9 u1 a7 L+ V
typedef struct QFsmTag QHsm;. }, l) [! z- |1 \4 _  b. `
" C  x# m' V, e9 X  X; Y% s$ S( B
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */
% d; R6 u5 u" Z# f: G& F
#define Q_IGNORED()         (Q_RET_IGNORED)  ~+ K7 P' L9 ?6 P
/* 已处理事件 */
+ o2 V; d& Z5 T#define Q_HANDLED()         (Q_RET_HANDLED), s3 m4 W" V6 l; K/ [+ Q
/* 状态转移 */- O! g) B. k, q& B! d- l( S
#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)
* C1 [" s! @9 t- G  Y  ?3 q/* 到超状态 */* z+ m8 W' ^/ V2 E. H- y  B
#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER)( x5 v* _( t7 ~. A( E+ f
9 ~3 S, ]( p3 s" T( N4 s; N" z
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */
+ g9 X% G+ v- B, Z' W/ n# e* ^+ z9 |
#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))
! _6 I* U! g* R2 K/* 触发退出动作,在层次状态机HSM */
8 g1 [+ a3 z; @% s' m#define QEP_EXIT_(state_)     
* w  X# ~! j" e, pif (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED)
8 A7 J; Z1 b6 @& s6 U{
. m5 T+ ]. v0 u3 P' H         ...QS     
. o# i' J! X) t" B& T8 ]4 \}, m) P5 I9 V) L7 v8 B

# Q5 Y# Z% C9 {! }9 Y9 M5 c; D8 _1 m
4 @- F# ]6 E* r2 M6 M
/* 触发进入动作,在层次状态机HSM */
( A; p. U2 n/ c1 H# u  a#define QEP_ENTER_(state_)     
4 z% b$ a1 b/ C+ {; \  o' mif (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED)
2 P$ X" I% P6 {- d{
  e4 @7 ^( S# Y& ~7 e         ...QS     
6 B2 c! I9 N) `, q  B}- t0 H/ R* ?; N( u7 G1 W
0 f9 I, \( i2 O% ^$ q
7 D1 P7 F0 ~1 o, j# j
/* 触发空动作,在层次状态机HSM (自加)*/! S! L; W0 l3 T- }
#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  
/ R( j) _" M8 b1 N! W; U
9 y" K) G7 K1 ^1 Q! M' Q' w2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程$ R/ p+ {4 n" m  f$ G. ?
815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程: z' k" y" w9 @3 x7 c% v
815490-20151227210907999-1694829155.png 

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

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

(1)QHsm_init()流程
- K. m: [7 B1 ?5 } 815490-20151227210908374-1012628730.png 

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

(2)QHsm_dispatch()流程  L4 W, S/ \* B8 c. b+ a4 I# D
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-12-13 17:08 , Processed in 0.033053 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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