C語言實現協程(coroutine)

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這樣的關鍵字,那麼如何做到一個函數的來回切換呢?

  1. 使用靜態變量記錄函數執行狀態。
  2. 使用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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章