C 程式設計/協程
鮮為人知的是,大多數 C 實現都內建了可用於協作式多工/協程的原語。他們是 setcontext 和 setjmp.
函式setjmp與longjmp成對使用,用於將執行轉移到程式碼中的不同位置。它依賴於現有的jmp_buf宣告。
#include <setjmp.h>
int main (void)
{
jmp_buf buf1;
if (setjmp(buf1) == 0)
{
/* This code is executed on the first call to setjmp. */
longjmp(buf1, 1);
} else {
/* This code is executed once longjmp is called. */
}
return 0;
}
setjmp()將當前執行點儲存在記憶體中,只要包含該函式不返回,該記憶體就保持有效。它最初返回0。當longjmp使用原始jmp_buf和替換返回值呼叫時,控制權將返回setjmp。
請注意,jmp_buf 在沒有使用地址運算子的情況下傳遞給 setjmp。
理解 setjmp 和 longjmp 的最簡單方法是,setjmp 會儲存 CPU 的狀態,包括程式計數器、堆疊指標、所有暫存器(包括標誌暫存器的位),在由 jmp_buf 指向的位置,該位置定義為 LEN+1,這足以儲存所涉及的任何 CPU 的暫存器。longjmp(buf) 從不返回,因為它從由之前的 setjmp 呼叫設定的結構 jmp_buf buf 的內容中恢復 CPU,因此執行從 setjmp 被呼叫之後開始,但 setjmp 的返回值不是 0,而是 longjmp 中第二個引數使用的任何值。這類似於 fork() 系統呼叫,它返回 0 給子程序,並將子程序的 PID 返回給父程序。
網際網路建議協程對於將軟體實現為協作狀態機很有用,例如詞法分析器處理輸入文字併發出標記,以便解析器可以決定儲存標記並請求下一個標記,或對其當前的標記集採取行動。這並不是多執行緒程式在資料上同步,如果出現錯誤,忘記獲取鎖會導致競爭條件,而是使用 setjmp 和 longjmp,似乎是協作程序,保證一次只執行一個程序,無需擔心上下文切換喚醒睡眠程序(使用單獨的 jmp_buf 靜態位置,每個程序可以在呼叫 longjmp 後呼叫 setjmp 獲取自己的 jmp_buf,如果返回 0,或者繼續迴圈處理非零返回值的共享資料)。