一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

手机号码,快捷登录

手机号码,快捷登录

搜索
查看: 4016|回复: 0

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

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑
1 y9 V9 r: F" w: s# I% G5 p
: z! |# R8 |6 `1 I  KQEP之init()和dispatch()流程图
# R9 v6 j, t/ O; d/ m
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。
# R! v: r& t3 E0 V: a5 w5 W- e' Z% J
     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。

- q' y2 j2 F" xtypedef uint8_t QState;                           

! {5 N; R" Q( b) L, e
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/+ o4 p" [( I$ F- n* S7 |  N, p  y

( X' d; ]5 h# d, A
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   

9 }: [8 p* S: [* b) Y! n1 NQStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/
3 z* U6 J3 L% `} QFsm;
: a/ H' t7 H! U8 G1 C6 k4 p+ S$ C' T  F0 d/ Z: g3 L0 }
typedef struct QFsmTag QHsm;
- @2 D9 e3 t6 J  l
* g. e5 O" [/ c( {. B+ J; R" Y
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */

# G/ v; O. F) `( J( G#define Q_IGNORED()         (Q_RET_IGNORED)
4 u8 [  h0 `, R3 X& I/* 已处理事件 */- t9 N3 r! F1 W. l: M& V3 s
#define Q_HANDLED()         (Q_RET_HANDLED)
& t; x: z' z7 e  J, Q% z  @, f/* 状态转移 */+ {$ r% t4 M- G. _. r4 I- W
#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)9 L1 a/ Z" J/ s& H# m
/* 到超状态 */
; e/ ~9 ?& n. e9 s#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER)! h+ M1 S' Z! J/ w4 |+ S8 V7 ~

6 r4 q9 t8 O  I1 f
(4)触发动作
dispatch()用于主动去触发具体状态机,以探知状态机的结构、执行进入和退出动作。用QEP_EMPTY_SIG 触发空动作,总是会执行到状态函数的最后一行 QSUPPER(super_),通过触发后的返回结果,可以探知状态机的层次结构。
/* 以sig_信号触发状态机 */

6 b4 u+ m% E7 C5 q#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))- T; f  j+ k; I: w, n
/* 触发退出动作,在层次状态机HSM */
! p1 u: R3 s( I9 y#define QEP_EXIT_(state_)     
( m. b$ [, e1 Y7 sif (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) . L8 R8 l5 @) k% [
{# X5 U; x) H3 p! @# S8 N: f
         ...QS     - |$ v5 F* m5 g! J% t
}
. S/ H3 T5 O- y; a
2 \4 L; M* V- f

3 f! O' ~- C& E* ~  ?% L' l% Q/* 触发进入动作,在层次状态机HSM */
9 b5 y3 u. h8 [) H#define QEP_ENTER_(state_)     
& b& L9 _: q2 Aif (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) 1 x6 C& X# Z+ p0 G( \7 ~, K
{# g' S8 X. X5 m1 C' I9 [& h$ J  R
         ...QS     ! N# ~( r% @/ }; Q" E* g3 ?
}
, z6 @8 s, c' d, y* H4 t2 T3 R  R  ~& F9 j& G1 l' f
1 ?+ z0 P2 \% q4 [
/* 触发空动作,在层次状态机HSM (自加)*/
: s% a$ o# N$ e' J/ y, z#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  , t- T+ F3 U- R8 h4 Q1 T
( m) z6 a' q% O  S* L. I
2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程
* F& d, V" {+ g 815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程
+ ?! b& h5 b) V 815490-20151227210907999-1694829155.png 

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

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

(1)QHsm_init()流程
* S- ?8 C4 _2 c4 |" r; A 815490-20151227210908374-1012628730.png 

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

(2)QHsm_dispatch()流程! B( p- v: G: ]* |
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-4-17 16:28 , Processed in 0.037114 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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