说明
- 循环事件是编程中比较常见的事件之一,各种编程语言都有循环语句来处理循环事件,使用循环语句有个前提:事件处理可以拆分为多个拥有共同模板的子任务,大部分情况下使用循环语句可以很方便的处理循环事件,但是依然有些特殊场景处理起来不是很方便。
处理
普通情况
- 任务可以拆分为多个拥有共同处理模板的子任务,如下:
while (条件){
子任务
}
* 子任务由多个步骤组成
while (条件){
子任务步骤1
子任务步骤2
}
特殊情况
- 数据处理时,部分数据可循环处理,但是前部分数据是一次循环的部分,详细描述如下:
- 循环处理的单次处理可以拆分为多个不同的步骤,例如:A,B,C分别为不同的子任务,循环处理为A,B,C,A,B,C,…,如果循环需要支持可重入,由于循环重入时,初始状态不同,执行的起始点不一样,处理流程可能为B,C,A,B,C… 或者 C,A,B,C…,如下场景:
- Base64编码,3个字节的原始数据编码成4个字节,每个处理单元(3个字节)中的每个字节的处理都是不同的,因此每个处理单元可以分成3个步骤,编码时可能是分段处理的,并不是一次调用(即编码函数可能被调用多次),每次调用的第一个字节,可能是完整编码中的第1个字节,也可能是第2个字节,也可能是第3个字节,因此处理不同。
- wifi联网处理,联网有多个步骤:wifi 网口设置、wpa_supplication 配置、dhcp 获取ip、route 设置路由、判断外网是否联通…,联网时需要按步骤执行,由于每个步骤都有可能失败,失败后重新联网,进入该函数时可能有多种起始状态。
处理方式
while (run)
{
switch (step) //当前step
{
case step_A:
...; //执行处理
step = step_B;
break;
case step_B:
...; //执行处理
step = step_C;
break;
case step_C:
...; //执行处理
step = step_A;
break;
}
}
- 如果每一个步骤的下一个步骤是固定的,以上写法每次都需要设置和判断下一步,会浪费些性能。
- 近日阅读libb64源码,发现以下写法:
* 文件:cencode.c 函数:base64_encode_block
int base64_encode_block(const char* plaintext_in, int length_in, char* code_out, base64_encodestate* state_in)
{
...;
switch (state_in->step)
{
while (1)
{
case step_A:
//判断处理是否需要结束,如需结束,保存当前step,不需结束,执行相应处理
...;
case step_B:
...; //类似step_A
case step_C:
...; //类似step_A
}
}
}
- cencode.c的作用是Base64编码,Base64编码时3个字节的原始数据编码成4个字符数据,每三个字节处理是一样的,但是三个字节中编号为0,1,2的处理是不一样。
- base64_encode_block函数的作用是编码一段数据,可以多次调用。多次调用该函数时,数据的第一个字节在所有数据中的位置是不一定的,可能是0,1,也可能是2,循环的起始状态不固定。
- 该方式有以下优点
- 性能好,该处理不等同于做法1,性能好于做法1,不需要每次设置和判断当前step。
- 支持多次重入调用,可根据上一次执行完保存的step值从正确的step开始执行,重复调用时不需要做额外处理。