一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4201|回复: 0

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

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑 * h9 H' w" z2 G% O, D
. p5 _6 O: [  {7 b- h/ X) D$ D- l
QEP之init()和dispatch()流程图. W/ x; q$ P' J+ ]: P8 i; b
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。

$ q! e0 d" ]) |. @  w1 D     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。

! u* o0 T" ]9 h& \* _typedef uint8_t QState;                           

, s* b7 d+ B; R9 E$ d: K
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/
  y/ V2 i9 R9 F) G& O, T+ [3 X
  e9 f7 m4 Z, k3 T1 n
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   
! f) N! K% |9 G/ c0 \  o
QStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/, [& x/ W6 r2 J6 M
} QFsm;! }* q3 h2 n3 H, X- ^8 F2 @( v
3 A; I0 x0 v7 N- E" J" }7 r) Y
typedef struct QFsmTag QHsm;
+ B* F8 a# R; M- b+ Y3 V( R. F5 A$ |, |8 [! f; [+ {* B
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */

9 {: F: U1 g7 X8 d; @#define Q_IGNORED()         (Q_RET_IGNORED)
9 N2 B* s9 v- R0 p/ L/* 已处理事件 */# C. A( Q* C" U" X. `5 [
#define Q_HANDLED()         (Q_RET_HANDLED)) z9 S& ]0 L7 R) C& o8 o, U4 C  Z
/* 状态转移 */
7 _) V  l$ J7 M* ?0 S#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)! F' n. A2 N9 h+ d; {
/* 到超状态 */
/ W$ _. l* e) q% g" ?#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER)
7 A, V. F& [  |7 I  Z/ h
9 q6 D  C" v4 R
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */
  C; E4 H8 I* v4 x$ w
#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))
% m* `- p& p; ~  w9 ^" b/* 触发退出动作,在层次状态机HSM */6 t+ t- _. ~" e5 ?+ g
#define QEP_EXIT_(state_)     
$ Q8 M# b9 q0 T3 i1 g: n/ Pif (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED)
* J" ^6 U2 y  O{
% l/ X. C8 a  T8 z7 e         ...QS     + j  D" v$ g! @3 w
}
2 M: y5 z: D9 @
2 h* k' _( E% o( ?1 Q

5 e- N- n, o0 \/ A2 @8 ]" |  K/* 触发进入动作,在层次状态机HSM */8 U& [, F% v0 b( Z! D
#define QEP_ENTER_(state_)     $ m) h; m# ^7 M0 `& b
if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) 0 ~& Q! z2 w* b
{: M2 G+ I$ S3 H  Y0 K
         ...QS     : D' W2 j' F3 f# V
}3 @# V" C2 k3 E' w) G" i
2 k2 j2 f- Y7 N+ e

/ r7 M, y2 I2 F) K( `2 F/* 触发空动作,在层次状态机HSM (自加)*/
/ r* X5 w9 A% ]- k1 F% N+ R#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  ' n( z0 S9 x; L( s# b

( e! ]4 D  ?* Z3 g" m2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程  M) \% p4 [7 o( o- W& y
815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程
8 L0 N: P0 g5 A& [ 815490-20151227210907999-1694829155.png 

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

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

(1)QHsm_init()流程
- a; s# \0 ~6 M" }" y& ~5 `1 ^. ` 815490-20151227210908374-1012628730.png 

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

(2)QHsm_dispatch()流程* g! N( e& E  \5 t) T' W
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-7-13 06:39 , Processed in 0.029837 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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