一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

搜索
查看: 3429|回复: 0

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

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑 ) e) e6 U% ^; y4 H! o

% Z7 P# p) f5 G& \5 J$ h% GQEP之init()和dispatch()流程图" j2 y1 y7 E& A% B% q
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。
- j) r% ]# O2 T& E* ^2 d
     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。
. Y% O/ u  ^. `
typedef uint8_t QState;                           

6 V* C; d$ L2 Y/ L8 ^4 ^
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/
; R/ L7 N: E) n" _4 r6 s% B4 d* A( A, P1 b" I, \! k
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   

3 y# }. p1 X; f3 N3 o* eQStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/
! s! B; E, c6 B) i; F' s) j} QFsm;
3 B2 c6 W8 _+ T3 F( S# C
2 L) W3 ?6 p4 p
typedef struct QFsmTag QHsm;1 @- s- r9 B! M( e) W  o

* W3 f; w! z& K- O( v4 S
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */
1 ]  R/ n; d% I8 c* O& N
#define Q_IGNORED()         (Q_RET_IGNORED)
1 u' l6 t, ^; z% v8 H  Q! r% N+ y/* 已处理事件 */
# u  C% y( Y! g2 _8 ^. R2 f7 B#define Q_HANDLED()         (Q_RET_HANDLED)' @* `" @# y; O+ T- ]' d
/* 状态转移 */, \8 b8 |" t- Z' U8 s
#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)7 P, g3 P* d% {% @0 M5 a
/* 到超状态 */6 V: ^; n1 _, j$ B* I' w, e& _
#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER)  {) S( n( ]7 D/ ~' _
5 h0 l+ L7 _' o2 M% O+ \# M
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */

  E, \- N+ K. V6 B0 B/ D& Z# P5 Z#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))
6 Q. `$ {# V+ g/* 触发退出动作,在层次状态机HSM */
2 u1 ]- T! A: y! X, r. z! h# n0 P' s#define QEP_EXIT_(state_)     8 u4 l- m# j! N" n
if (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED)
0 l9 u# f6 Y. h0 r7 X{, ~, e8 h7 Y) |
         ...QS     
1 t6 l4 T5 Y9 m7 R8 s}+ O6 W/ t+ B3 u  y
; {. Z0 t* o' f. O$ `$ q
7 C, _! \6 ^( S2 G
/* 触发进入动作,在层次状态机HSM */- y6 t9 f0 K/ t( U* j
#define QEP_ENTER_(state_)     * H2 S+ R6 p6 O0 Y9 D: C) D; q1 \
if (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED)
+ _( g, O+ o2 l" H{0 P4 d6 I* v1 t* }
         ...QS     - |+ w7 R. V2 K+ m
}4 }* F& K- q" ]+ }' l
( c, ]$ h! a5 R0 ]' q
" D7 H' v6 d; X8 {4 h, P
/* 触发空动作,在层次状态机HSM (自加)*/3 g* i* L  `. S9 q; I
#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  6 Z( z$ V: D, x7 c/ v' }8 N
7 F) ?4 ~+ a. u3 s- `
2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程6 }0 a' k# h# M1 M
815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程
3 _5 W! G" |5 X' \8 \/ c! Q! N 815490-20151227210907999-1694829155.png 

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

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

(1)QHsm_init()流程
+ I' N+ w' @7 g8 {/ h 815490-20151227210908374-1012628730.png 

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

(2)QHsm_dispatch()流程, x3 ^) F# }) y0 P3 B
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-8-20 09:02 , Processed in 0.055422 second(s), 30 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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