考慮一個簡單的Python函數(shù):
def gen():
for i in range(10):
yield i
是否有可能在C或者C++中實(shí)現(xiàn)呢?
在Coroutines in C一文中詳細(xì)的介紹了在C語言中實(shí)現(xiàn)的可能性运吓。
現(xiàn)在簡單介紹下:
版本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記錄下上次退出函數(shù)時的狀態(tài),在下一次進(jìn)入函數(shù)時通過判斷state并利用goto語句跳轉(zhuǎn)到上次退出的位置仔拟。
這種方法不夠直觀荡含,寫起來比較麻煩,因此可以利用Duff's device來進(jìn)行改造硼补。
Duff's device利用了switch語句也可以進(jìn)行跳轉(zhuǎn)的原理:
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更加直觀,然后可以定義宏來進(jìn)一步簡化書寫熏矿。
版本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已骇,要設(shè)置給crReturn的第一個參數(shù)都各不相同,這樣比較麻煩曲掰,可以利用自帶宏__LINE__進(jìn)一步簡化:
版本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庫中,有專門的實(shí)現(xiàn):
Boost.Coroutine
該庫的部分實(shí)現(xiàn)使用了匯編語言栏妖。