|
楼主 |
发表于 2015-5-4 14:12:46
|
显示全部楼层
本帖最后由 sunliezhi 于 2015-5-4 14:19 编辑
之二: Bomb状态机初始化
从 main() 可知,初始化是从 bomb_test()开始的
历经 event_init(),
来到 Bomb4_ctor(&l_bomb22, 0xd),
其中 l_bomb22是Bomb4的实例, 定义在 bomb.c: Bomb4 l_bomb22;
0xd 是停止倒计时密码
查看Bomb4_ctor()原型:
static void Bomb4_ctor(Bomb4 *me, RAW_U8 defuse)
{
FSM_CONSTRUCTOR( &me->a1.super,
(stm_state_handler)&Bomb4_initial);
me->defuse = defuse;
}
即是执行如下语句:
{
FSM_CONSTRUCTOR( &l_bomb22.a1.super,
(stm_state_handler)&Bomb4_initial);
l_bomb22.defuse = defuse;
}
由 FSM_CONSTRUCTOR() 原型 #define FSM_CONSTRUCTOR(me, initial) \
do { \
(me)->state = 0; \
(me)->temp = (initial); \
} while (0)
可知 Bomb4_ctor(&l_bomb22, 0xd) 即是执行了:
{
&l_bomb22.a1.super.state = 0;
&l_bomb22.a1.super.temp = Bomb4_initial;
l_bomb22.defuse = 0xd;
}
即给函数指针赋初始值, 给密码变量设置密码
(后来的setting与timing状态之间的转换就是修改这两个函数指针!)
至此 Bomb4_ctor(&l_bomb22, 0xd) 执行完毕!
继续......
来到 fsm_init(&l_bomb22.a1.super, 0); fsm_init()函数的原型就不列了
一开始检查 &l_bomb22.a1.super.temp 是不是被设置了,未设置则停机!
由上面可知 &l_bomb22.a1.super.temp被设置指向了 Bomb4_initial 函数
接下来执行指针函数,即是 执行 Bomb4_initial(),看函数原型:
static RAW_U16 Bomb4_initial(Bomb4 *me, STATE_EVENT *e) {
(void)e;
me->timeout = INIT_TIMEOUT;
return STM_TRAN(&Bomb4_setting);
}
又看 STM_TRAN()原型:
#define STM_TRAN(state) \
(((STM_STRUCT *)me)->temp = STM_STATE_CAST(state), \
STM_RET_TRAN)
以前看 txj 大牛说到 C语言实现面向对象的继承、强制向父类提升.....
这里 (STM_STRUCT *)me 就是:
me 在这里是 Bomb4类型的变量
Bomb4继承了 ACTIVE_EVENT_STRUCT类型
而 ACTIVE_EVENT_STRUCT又继承了STM_STRUCT
所以 (STM_STRUCT *)me 是向上提升了2级!
由上分析可知初始化函数设置了 Bomb爆炸前的倒计时数值;
又设置 l_bomb22.a1.super->temp = Bomb4_setting
并返回值 STM_RET_TRAN
至此 Bomb4_initial()执行完毕!
继续.....
判断返回值是否是 STM_RET_TRAN, 没错啦
继续.....
STM_TRIG(me->temp, STM_ENTRY_SIG);
看 STM_TRIG() 原型:
#define STM_TRIG(state, sig) \
((*(state))(me, &STM_GLOBAL_EVENT[sig]))
实际上就是执行指针函数 l_bomb22.a1.super->temp,即 Bomb4_setting()
输入的参数是 STM_ENTRY_SIG
去看看 Bomb4_setting()中的 case STM_ENTRY_SIG:
static RAW_U16 Bomb4_setting(Bomb4 *me, STATE_EVENT *e)
{
switch (e->sig)
{
case STM_ENTRY_SIG:
{
me->code = 0; /* clear the defuse code */
return STM_RET_HANDLED;
}
.....
很简单,清零用户输入
继续......
me->state = me->temp; 同步,即设置函数指针 state:
l_bomb22.a1.super->state = Bomb4_setting
至此 fsm_init(&l_bomb22.a1.super, 0) 执行完毕!
最后就是 打印开机提示信息。。。。。
至此 bomb_test() 执行完毕,返回 main() 去执行其它初始化。 |
|