一乐电子

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

QQ登录

只需一步,快速开始

微信扫码登录

搜索
查看: 3430|回复: 0

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

[复制链接]
发表于 2018-4-19 10:51 | 显示全部楼层 |阅读模式
本帖最后由 kenson 于 2018-4-19 11:15 编辑
# E9 m" V6 V* e+ N2 b2 T
! a6 O" O$ n: H/ bQEP之init()和dispatch()流程图
$ t  \/ }- Z7 x
抽象状态机类QFsm或QHsm有一个函数指针,用于在继承的具体状态机类中指向具体的状态函数,其有两个对外的接口函数init()和dispatch(),其工作原理是理解状态机处理事件过程的关键。
具体状态机类继承自QFsm或QHsm,同时继承了这个函数指针,用于动态指向具体状态机类中的私有状态函数。
具体事件继承于根事件QEvent,并可以自己增加附加的属性。事件是外部与状态机唯一通信的实体,通过dispatch(),把事件送到状态机。状态机对外不可见,具体属性和具体状态函数都是私有的。

8 X3 v: {+ e1 X. L4 G8 U     图1.QEP总体类结构1.预备知识
(1)声明一个函数指针
具体状态机类继承自QFsm或QHsm,则具体状态机具有了一个指针state,state可以指向任何状态函数,并调用状态函数执行。dispatch()函数可以用空事件探测状态机的结构、可以执行进入和退出动作、可以执行具体的事件处理动作,也可以进行状态转移。
& r& G  p  e! t' v/ X6 e; b7 X
typedef uint8_t QState;                           
5 O, u# E; {* N8 w1 t. Q% Y$ ^8 r
typedef QState (*QStateHandler)(void *me, QEvent const *e);/*函数指针*/
; P, \$ T. }0 A# V! T
2 |, c. v" V9 W) d6 I6 I
(2)声明一个状态机中的函数指针变量
typedef struct QFsmTag {   
7 q6 n' c) f8 B7 X" Y$ S/ r
QStateHandler state; /*变量(函数指针),指向状态机当前状态(函数)*/
. ~+ e% S7 M+ V5 V} QFsm;( M0 n4 M  F& @" l) x" u1 `+ h

$ r9 A! J2 [6 H- X& n' L
typedef struct QFsmTag QHsm;
" V1 E2 N9 M8 d4 u+ q" L5 n6 S6 Y+ ~& `5 G4 C7 C
(3)状态函数处理后的返回结果
每个状态函数中,根据不同的事件处理,处理完后要返回上边的结果之一,供dispatch()了解状态函数对某事件是否忽略、是否处理完、是否转换、是否不能处理而要让父状态函数来处理。
QSUPP(super)中的参数决定了层次状态机的层次结构。
/* 忽略事件 */
" q9 T" ^& g9 n3 K6 J) J9 q
#define Q_IGNORED()         (Q_RET_IGNORED)
$ D7 D5 J4 _1 q/* 已处理事件 */
" z" O5 t4 d  D/ u3 [5 G#define Q_HANDLED()         (Q_RET_HANDLED)
8 ^5 u* ~! J7 v4 e/* 状态转移 */7 v$ I4 S7 M/ m# d$ t
#define Q_TRAN(target_)      (((QFsm *)me)->state = (QStateHandler)(target_), Q_RET_TRAN)
! J& h( r) g' ~8 Q/* 到超状态 */  S& ~: q0 d/ ~% J1 H. K  d$ |
#define Q_SUPER(super_)      (((QHsm *)me)->state = (QStateHandler)(super_),  Q_RET_SUPER)7 S$ M5 \" s5 L" L( A  B

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

1 q8 @( \- f: @; J+ c#define QEP_TRIG_(state_, sig_)     ((*(state_))(me, &QEP_reservedEvt_[sig_]))
* i" j: `- U( t/* 触发退出动作,在层次状态机HSM */
! W( M* e' p4 y. A, X: O8 b#define QEP_EXIT_(state_)     
( V# j9 H6 T1 v. ~% A* Q+ cif (QEP_TRIG_(state_, Q_EXIT_SIG) == Q_RET_HANDLED) / C9 E  @" f( i  B4 q# o' C! D* {
{
2 R( l5 E1 H" _. K$ s3 a         ...QS     
3 L, |- @3 M! F' l% G' T" M}
' K7 {) S; M) s0 R( x
0 ?" _5 l( c) J# P
$ k/ n, ]6 U, `4 {* F9 [; F2 D3 ~
/* 触发进入动作,在层次状态机HSM */
1 W9 s6 N- @2 o) Y$ ?#define QEP_ENTER_(state_)     
" i9 e& q: ~  @5 P4 t: r1 iif (QEP_TRIG_(state_, Q_ENTRY_SIG) == Q_RET_HANDLED) ) c# O+ l- s6 {0 I
{* L$ y2 v) Y# ?4 z* z
         ...QS     ( N5 W) O* y3 [4 C+ `. L7 _
}# s" ~/ \  N4 P+ R" n9 z8 S2 G9 E& n. L
& v1 A! t0 C4 O5 V; i8 n! T0 V2 ~
1 s0 L; G. L% B% X& X# X* S
/* 触发空动作,在层次状态机HSM (自加)*/; H/ O( g/ _" a' ]9 j% u
#define QEP_EMPTY_(state_)     QEP_TRIG_(state_, QEP_EMPTY_SIG_)  
+ O& L6 E0 x9 r6 |8 S& {
' v4 t: A, G/ H3 R" ?7 \2.Fsm状态机init()和dispatch()流程

(1)QFsm_init()流程  O1 |' P2 R. D$ W8 j1 S8 g' F' P$ H
815490-20151227210907906-1888535234.png 

   图2.QFsm_init()流程

(2)QFsm_dispatch()流程
$ p7 j8 \2 }  Q, i% ?8 W9 S' K) | 815490-20151227210907999-1694829155.png 

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

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

(1)QHsm_init()流程7 h8 j4 }# e# U( R
815490-20151227210908374-1012628730.png 

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

(2)QHsm_dispatch()流程7 S# e4 t& N4 g- u2 F  N$ E
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:04 , Processed in 0.032478 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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