Donald Knuth 說過:
“子程序就是協程的一種特例。”
編程過程中,最常用的就是函數調用,這時對於調用方來說,被調函數就是子程序(subroutine)
。可以把協程理解相互配合工作的函數,函數之間可以相互切換,並且能夠從上次切換的狀態重新開始執行。
python 程序中的 yield
關鍵字可以將一個函數停止執行並保持執行狀態,等待再次被調用。
def rangeN(a, b):
i = a
while (i < b):
yield i
i += 1
for i in rangeN(1, 5):
print(i)
如果把協程理解成相互配合工作的函數,那麼如何理解“子程序就是協程的一種特例。”
這句話呢?
在經典的c程序中,函數的調用是基於棧進行的,函數調用結束後所有信息出棧,被調函數結束執行,狀態丟失。c語言沒有yield
這樣的關鍵字,那麼如何做到一個函數的來回切換呢?
- 使用靜態變量記錄函數執行狀態。
- 使用
goto
關鍵字跳轉到必要的執行點。
int rangeV2(int a, int b) {
static long long int i;
static int state = 0;
switch (state) {
case 0:
state = 1;
i = a;
while (i < b) {
return i;
L:i++;
}
state = 0;
return 0;
case 1:
goto L;
}
}
int main() {
int i;
//for (; i = range(1, 5);) {
// printf("debug>>>>>%d\n", i);
//}
//
i = rangeV2(1, 5);
while (i != 0) {
printf("debug>>>>%d\n", i);
i = rangeV2(1, 5);
}
}
如果不想使用goto
關鍵字,可以使用 duff’s device (什麼是達夫設備,參考這篇文章) 來實現:
int range(int a, int b) {
static long long int i;
static int state = 0;
switch (state) {
case 0:
state = 1;
//for (i = a; i < b; i++) {
// return i;
// case 1:;
//}
i = a;
while (i < b) {
return i;
case 1:
i++;
}
}
state = 0;
return 0;
}