C语言C++

利用Duff's device在C/C++中模拟Pyth

2017-02-01  本文已影响175人  华山论剑

考虑一个简单的Python函数:

def gen():
    for i in range(10):
        yield i

是否有可能在C或者C++中实现呢?

Coroutines in C一文中详细的介绍了在C语言中实现的可能性。

现在简单介绍下:

版本1:

int gen(void) {
    static int i, state = 0;
    switch (state) {
        case 0: goto LABEL0;
        case 1: goto LABEL1;
    }
    LABEL0: /* start of function */
    for (i = 0; i < 10; i++) {
         state = 1; /* so we will come back to LABEL1 */
        return i;
        LABEL1:; /* resume control straight after the return */
    }
}

版本1利用static变量state记录下上次退出函数时的状态,在下一次进入函数时通过判断state并利用goto语句跳转到上次退出的位置。
这种方法不够直观,写起来比较麻烦,因此可以利用Duff's device来进行改造。
Duff's device利用了switch语句也可以进行跳转的原理:

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 ((count -= 8) > 0);
}

版本2:

int gen(void) {
    static int i, state = 0;
    switch (state) {
        case 0: /* start of function */
        for (i = 0; i < 10; i++) {
            state = 1; /* so we will come back to "case 1" */
            return i;
            case 1:; /* resume control straight after the return */
        }
    }
}

版本2相对于版本1更加直观,然后可以定义宏来进一步简化书写。

版本3:

#define crBegin static int state=0; switch(state) { case 0:
#define crReturn(i,x) do { state=i; return x; case i:; } while (0)
#define crFinish }
int gen(void) {
    static int i;
    crBegin;
    for (i = 0; i < 10; i++)
        crReturn(1, i);
    crFinish;
}

版本3中如果有多个crReturn,要设置给crReturn的第一个参数都各不相同,这样比较麻烦,可以利用自带宏__LINE__进一步简化:

版本4:

#define crBegin static int state=0; switch(state) { case 0:
#define crReturn(x) do { state=__LINE__; return x; \
    case __LINE__:; } while (0)
#define crFinish }
int gen(void) {
    static int i;
    crBegin;
    for (i = 0; i < 10; i++)
        crReturn(i);
    crFinish;
}

对于C++,在boost库中,有专门的实现:
Boost.Coroutine
该库的部分实现使用了汇编语言。

上一篇 下一篇

猜你喜欢

热点阅读