一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 3916|回复: 0

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

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑 ! T0 Z( J2 F# k8 |; G

" \) g# ^# a4 N- N) ZQEP之init()和dispatch()流程图" Q& c) c) g+ @  A7 X  {
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。
" ^" G' ]+ X% O  w, {/ n0 I
     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。

" m1 T' J7 w# e, [* O6 f8 Stypedef uint8_t QState;                           

# ?% f! S0 A7 r$ k
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/' G" R) b- U) M4 z2 G: q: |9 a

9 H2 w; M7 w0 x1 _# V
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   
) P( R( B* F  V& b7 r$ ?3 g
QStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/% U, y- O! O5 l3 L, P0 c
} QFsm;
* e9 m4 c2 q- Y( r4 v# ~6 l/ F( t4 ^+ j6 M3 c4 E. V
typedef struct QFsmTag QHsm;1 ?0 ?. T+ q2 ?% }& t0 X; j

& T+ E* ~5 f) y2 J+ k. e
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */
. ~1 |+ G6 J* c1 t# N) b8 Z
#define Q_IGNORED()         (Q_RET_IGNORED)
# B4 S! g& l' p0 F" L/* 已处理事件 */3 ^! y  c/ f4 j6 p7 @9 _8 F
#define Q_HANDLED()         (Q_RET_HANDLED)9 r0 U6 H+ ]7 R9 C8 l
/* 状态转移 */
% y2 P! w% M3 k  [/ c( f: G# X/ u#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)1 K0 z& e4 n! P( ?- m+ `
/* 到超状态 */
' c. `" x3 `( z: |7 c) A, [#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER): m  h! H  H/ P6 V3 S( P

' k) Z9 W& i% v1 Z; ~
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */

8 |8 @6 ?2 a0 A) P. P6 B#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))
" `1 F: Q+ J- G% u  D. z/* 触发退出动作,在层次状态机HSM */
5 V+ P* j1 [4 H#define QEP_EXIT_(state_)     / j. M4 J$ O7 Q, I; s
if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED)
% P7 H0 Y4 V( P  d8 h0 P. l{
% Z  e- B- H+ y         ...QS     
/ B0 L5 y- S- S# {1 e+ H}& H9 E: {2 f; i( q5 y; V1 L

8 ?5 e4 a  C, s# ?  r
, D) Q4 {1 F, O' c- \8 f+ |
/* 触发进入动作,在层次状态机HSM */& S$ X, h/ V* w) c) D# X
#define QEP_ENTER_(state_)     
- v' ?# x) G7 P8 N: n7 D; e* z3 T; R  Aif (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED)
4 T; o# ^$ X9 Q: V5 Q' `{
, v# Q/ j' Y1 E7 P         ...QS     ; `0 U0 J9 H- O% t! p' I: v( d
}
8 u3 ~' X* m' L; T7 T2 T/ C8 \( }8 n  X

7 X' ?; Q7 c, |/* 触发空动作,在层次状态机HSM (自加)*/
: z$ T+ Q' N0 v#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  * J  e& F7 o' |
! R7 U. n( d  E8 {! p1 _/ g! [& ?
2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程
+ U1 R! O- y' I2 w& e 815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程" z: j8 k2 u5 D6 e- i
815490-20151227210907999-1694829155.png 

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

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

(1)QHsm_init()流程$ M' d6 ?* w! O0 w0 S9 E) L7 F
815490-20151227210908374-1012628730.png 

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

(2)QHsm_dispatch()流程6 s' h1 l5 I1 O$ y% P
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, 2026-2-25 13:15 , Processed in 0.033690 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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