看了 asio 的 \src\tests\latency\tcp_server.cpp 代码,被 coroutine 的 reenter 和 yield 的实现给震精到了……switch 和 for 穿插着,这居然也行,还有个学名叫“Duff's Device”!赶快写个测试代码,证明它是对的:
void foo(int n)
{
printf_s("---- %d ----\n", n);
switch (n) {
for (;;)
case 0:
if (1) {
printf_s("0\n");
break;
} else
case 1:
printf_s("1\n");
break;
default:
printf_s("default\n");
break;
}
}
int main()
{
foo(0);
foo(1);
return 0;
}
顺利编译,输出是:
---- 0 ----
0
---- 1 ----
1
0
好像不容易看懂,但是加上一些 {} 就容易了:
void foo(int n)
{
printf_s("---- %d ----\n", n);
switch (n) {
for (;;) {
case 0:
if (1) {
printf_s("0\n");
break;
} else {
case 1:
printf_s("1\n");
}
}
break;
default:
printf_s("default\n");
break;
}
}
大神的代码不容置疑,以下代码追求减少循环测试的执行次数。
void duff_memcpy(char* to, char* from, size_t count)
{
size_t n = (count + 7) / 8;
switch (count % 8) {
case 0: do { *to++ = *from++;
case 7: *to++ = *from++;
case 6: *to++ = *from++;
case 5: *to++ = *from++;
case 4: *to++ = *from++;
case 3: *to++ = *from++;
case 2: *to++ = *from++;
case 1: *to++ = *from++;
} while (--n > 0);
}
}
第一轮用 switch 选择进入点,以后每轮都是复制 8 字节。
扩展阅读:
《Asio 协程详解》https://www.avboost.com/t/asio/771