当前位置:首页 > 用状态机原理进行软件设计
QSTATE Calc_negated1(Calc *me, QEvent const *e); QSTATE Calc_operand1(Calc *me, QEvent const *e); QSTATE Calc_zero1(Calc *me, QEvent const *e); QSTATE Calc_int1(Calc *me, QEvent const *e); QSTATE Calc_frac1(Calc *me, QEvent const *e); QSTATE Calc_opEntered(Calc *me, QEvent const *e); QSTATE Calc_negated2(Calc *me, QEvent const *e); QSTATE Calc_operand2(Calc *me, QEvent const *e); QSTATE Calc_zero2(Calc *me, QEvent const *e); QSTATE Calc_int2(Calc *me, QEvent const *e); QSTATE Calc_frac2(Calc *me, QEvent const *e); void CalcClear_(Calc *me); void CalcInsert_(Calc *me, int keyId); void CalcNegate_(Calc *me); void CalcEval_(Calc *me); void CalcDispState(Calc *me, char const *s); END_CLASS calc.c
大体的思路跟QFSM类似,这里只举一个state的处理函数的例子。
QSTATE Calc_ready(Calc *me, QEvent const *e) { BOOLEAN is_handled = TRUE;
switch (e->sig) {
case Q_ENTRY_SIG:
CalcDispState(me, \ break;
case Q_INIT_SIG:
Q_INIT(Calc_begin); break; case IDC_0:
CalcClear_(me);
Q_TRAN_DYN(Calc_zero1); break; case IDC_1_9:
CalcClear_(me);
CalcInsert_(me, ((CalcEvt *)e)->keyId); Q_TRAN_DYN(Calc_int1); break;
case IDC_POINT: CalcClear_(me);
CalcInsert_(me, IDC_0);
CalcInsert_(me, ((CalcEvt *)e)->keyId); Q_TRAN_DYN(Calc_frac1);
break;
case IDC_OPER:
sscanf(me->display_, \ me->operator_ = ((CalcEvt *)e)->keyId; Q_TRAN_DYN(Calc_opEntered); break; default:
is_handled = FALSE; break; }
if (is_handled) {
return 0; } else {
return (QSTATE)Calc_calc; } }
分析:QHSM 是一套 HSM 的实现框架,它包括qhsm.h和qhsm.c文件等其他辅助文件。他的一些实现方法跟前面的 QFSM frame 类似,也是用函数指针代替状态。不过HSM 比 FSM 多了很多特性,以ready态的处理函数(Calc_ready)为例。描述一下QHSM的框架和 HSM 的执行情况:
2)SUPERCLASS QHsm中会记录Calc HSM instance的状态(函数指针)。当收到一个消息,QF框架会直接调用之。
3)状态的层次关系的体现:某个状态的处理函数中,如果这条消息需要这个状态处理,它的返回值就是0。如果本状态不处理,则返回其父状态的指针。比如 ready态会处理event IDC_0,它处理完毕就返回0,对于其他不处理的event则返回Calc_calc,也就是说其父状态就是Calc态。另外,QF自己定义了一个最顶层的状态叫QTop()。 4)QF自己定义了几个系统消息,包括:
Q_EMPTY_SIG = 0, //空消息,用于检测状态之间的父子关系的,外部不能响应这个消息。 Q_INIT_SIG = 1,//定义initial transition的消息,看代码,比如ready态的的初始状态是begin,当state transition到ready态以后,它就会自动迁移到begin态。 Q_ENTRY_SIG = 2, //Entry消息 Q_EXIT_SIG = 3 //Exit 消息
5)Transition:当调用Q_TRAN_DYN进行状态迁移的时候,QF会计算源状态和目标状态的公共父状态,会给源状态到公共父状态之间所有状态发送一个Q_EXIT_SIG 消息,然后给公共父状态到目标状态之间的所有状态发一个Q_ENTRY_SIG。
结论:前面用UML画的层次状态机用QHSM框架都能实现,而且把图翻译成代码也非常直观、方便。QHSM框架结构好,效率高,可重入。强烈推荐使用。 讲解完毕,别忘了我们的重点是:用状态机原理进行软件“设计”。
第9章 附录
附件是前面提到的CParser和Calc的实现。
SampleCode.rar
共分享92篇相关文档