一种使用函数指针实现状态机的方法
结构定义
假设s1为初始状态,状态变迁为s1->s2->...->sn。
常规实现
状态机处理函数state_machine_handle通常在一个循环内或被事件驱动框架调用,输入data会随时序变化,从而引起状态的变迁,伪代码框架如下。
sm->state初始化为s1。
1 struct state_machine {
2 int state;
3![]()
4 };
5
6 enum {
7 s1,
8 s2,
9![]()
10 sn
11 };
2 int state;
3

4 };
5
6 enum {
7 s1,
8 s2,
9

10 sn
11 };
常规实现
状态机处理函数state_machine_handle通常在一个循环内或被事件驱动框架调用,输入data会随时序变化,从而引起状态的变迁,伪代码框架如下。
1
void handle_s1(struct state_machine *sm, void *data)
2
{
3
//do something about state 1
4
if(is_satisfy_s2(data))
5
sm->state = s2;
6
}
7![]()
8
void handle_s2(struct state_machine *sm, void *data)
9
{
10
//do something about state 2
11
if(is_satisfy_s3(data))
12
sm->state = s3;
13
}
14![]()
15
void handle_sn_1(struct state_machine *sm, void *data)
16
{
17
//do something about state n-1
18
if(is_satisfy_sn(data))
19
sm->state = sn;
20
}
21![]()
22
void state_machine_handle(struct state_machine *sm, void *data)
23
{
24
switch(sm->state){
25
case s1:
26
handle_s1(sm,data);
27
break;
28
29
case s2:
30
handle_s2(sm,data);
31
break;
32
![]()
33
case sn:
34
handle_sn(sm,data);
35
break;
36
}
37
}
void handle_s1(struct state_machine *sm, void *data)2
{3
//do something about state 14
if(is_satisfy_s2(data))5
sm->state = s2;6
}7

8
void handle_s2(struct state_machine *sm, void *data)9
{10
//do something about state 211
if(is_satisfy_s3(data))12
sm->state = s3;13
}14

15
void handle_sn_1(struct state_machine *sm, void *data)16
{17
//do something about state n-118
if(is_satisfy_sn(data))19
sm->state = sn;20
}21

22
void state_machine_handle(struct state_machine *sm, void *data)23
{24
switch(sm->state){25
case s1:26
handle_s1(sm,data);27
break;28
29
case s2:30
handle_s2(sm,data);31
break; 32

33
case sn:34
handle_sn(sm,data);35
break;36
}37
}改进实现
为了免去丑陋的switch case分支结构,在state_machine内用成员函数指针handler替代了state,改进后的框架如下。
1
struct state_machine;
2
typedef void (*state_handler)(struct state_machine*,void*);
3![]()
4
struct state_machine {
5
state_handler handler;
6
![]()
7
};
8![]()
9
void handle_s1(struct state_machine *sm, void *data)
10
{
11
//do something about state 1
12
if(is_satisfy_s2(data))
13
sm->handler = handle_s2;
14
}
15![]()
16
void handle_s2(struct state_machine *sm, void *data)
17
{
18
//do something about state 2
19
if(is_satisfy_s3(data))
20
sm->handler = handle_s3;
21
}
22![]()
23
void handle_sn_1(struct state_machine *sm, void *data)
24
{
25
//do something about state n-1
26
if(is_satisfy_sn(data))
27
sm->handler = handle_sn;
28
}
29![]()
30
void state_machine_handle(struct state_machine *sm, void *data)
31
{
32
sm->handler(sm, data);
33
}
struct state_machine;2
typedef void (*state_handler)(struct state_machine*,void*);3

4
struct state_machine {5
state_handler handler;6

7
};8

9
void handle_s1(struct state_machine *sm, void *data)10
{11
//do something about state 112
if(is_satisfy_s2(data))13
sm->handler = handle_s2;14
}15

16
void handle_s2(struct state_machine *sm, void *data)17
{18
//do something about state 219
if(is_satisfy_s3(data))20
sm->handler = handle_s3;21
}22

23
void handle_sn_1(struct state_machine *sm, void *data)24
{25
//do something about state n-126
if(is_satisfy_sn(data))27
sm->handler = handle_sn;28
}29

30
void state_machine_handle(struct state_machine *sm, void *data)31
{32
sm->handler(sm, data);33
} sm->handler初始化为handle_s1,该方法在性能上应略优于常规方法,而且逻辑更清晰自然,非常适合于网络流的处理,在nginx中分析http和email协议时,得到了广泛应用。



浙公网安备 33010602011771号