一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3641|回复: 0

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

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑
8 J6 {. |4 u# |0 w) n. P; R1 }; f+ ]# L
QEP之init()和dispatch()流程图
4 X$ @1 \4 v  k
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。

; u! a1 d& `  Y& k# g     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。

4 w5 O. `' x! R2 E( t9 Ctypedef uint8_t QState;                           
! }8 {$ W- b3 q# z
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/7 y' `( Y' c  l
  S' Y/ H) K2 ^$ L
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   
5 R# w8 l, X5 M  F
QStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/0 R4 K) T& s2 |% J9 j! g( c1 ?# B
} QFsm;
, U! f) ?8 t, i2 G5 Y5 Y. B
+ T! e/ ~, J- i- {
typedef struct QFsmTag QHsm;- k4 `! N7 G. ?1 D4 y% P; H' n
+ s% m- z2 W2 Q+ n
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */

8 x( X; ~) Y( q3 y#define Q_IGNORED()         (Q_RET_IGNORED)
( M* G3 b' C3 n. ?2 Y! F/* 已处理事件 */
0 ^+ t' r$ i, d6 ?0 _/ Q#define Q_HANDLED()         (Q_RET_HANDLED)9 O5 U6 Y- w$ e
/* 状态转移 */
+ J3 |9 ?& ]. H/ S3 c4 E#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)
1 c) k  |+ d7 E/* 到超状态 */+ n5 p+ ^) `7 j# ?! Y8 M: L5 _
#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER)
# c2 l8 u3 S# R, \' T( u' [- z3 w# C5 V6 ^0 W1 M
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */

7 j6 z: t/ z7 T  _& N* I) t% C#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_])); e6 C1 ^( C6 u$ z; }& E, E7 f& R- Z
/* 触发退出动作,在层次状态机HSM */- i& ~/ h* W8 k# ^
#define QEP_EXIT_(state_)     ; G, q) D' v8 z+ Y
if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) 6 M! K- Q; [- O( ~# o
{
$ u1 h2 ?  k+ J9 u) X- w4 d         ...QS     + V5 f+ ]: w7 u+ c. \# J1 ~5 M
}) I+ T4 |5 x9 u
6 P3 D6 F8 y0 o  H% t. Z. ?! [
& D. F( K/ ?$ V
/* 触发进入动作,在层次状态机HSM */
! _$ W1 X  a5 H* ^4 r2 m#define QEP_ENTER_(state_)     
/ D) _( |3 x. N! n9 g0 \$ y$ qif (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) , y$ O- B. S; x' j; D
{. I1 ?. [3 B9 w6 N
         ...QS     
& Y, [/ y3 F, N' ^1 M}$ z2 d) t6 P4 X  K" s8 r+ o

" G  L9 K1 V( Z2 z+ ~4 X

2 ]! g- \2 b. s  f/* 触发空动作,在层次状态机HSM (自加)*/. s1 [5 ]! [! U0 e  n
#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  / t3 B  y# ^2 l% W# V6 c& X- _. D5 i- Y

. z1 r' L7 a* v7 m2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程
. k) v( K% k' O7 ]9 |$ w! v+ p9 X" a 815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程$ M. F( ~& B. b! P" ^( h
815490-20151227210907999-1694829155.png 

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

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

(1)QHsm_init()流程
' y  Z9 \# E* W0 f8 v6 I, c( ~* b 815490-20151227210908374-1012628730.png 

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

(2)QHsm_dispatch()流程5 P$ Q, I* O9 e, T8 _+ \
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-27 12:41 , Processed in 0.033759 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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