typedef struct _greenlet { PyObject_HEAD char* stack_start; char* stack_stop; char* stack_copy; intptr_t stack_saved; struct _greenlet* stack_prev; struct _greenlet* parent; PyObject* run_info; struct _frame* top_frame; int recursion_depth; PyObject* weakreflist; PyObject* exc_type; PyObject* exc_value; PyObject* exc_traceback; PyObject* dict; } PyGreenlet;
每一個(gè)greenlet其實(shí)就是一個(gè)函數(shù),以及保存這個(gè)函數(shù)執(zhí)行時(shí)的上下文.對于函數(shù)來說上下文也就是其stack..同一個(gè)進(jìn)程的所有的greenlets共用一個(gè)共同的操作系統(tǒng)分配的用戶棧.所以同一時(shí)刻只能有棧數(shù)據(jù)不沖突的greenlet使用這個(gè)全局的棧.greenlet是通過stack_stop,stack_start來保存其stack的棧底和棧頂?shù)?如果出現(xiàn)將要執(zhí)行的greenlet的stack_stop和目前棧中的greenlet重疊的情況,就要把這些重疊的greenlet的棧中數(shù)據(jù)臨時(shí)保存到heap中.保存的位置通過stack_copy和stack_saved來記錄,以便恢復(fù)的時(shí)候從heap中拷貝回棧中stack_stop和stack_start的位置.不然就會(huì)出現(xiàn)其棧數(shù)據(jù)會(huì)被破壞的情況.所以應(yīng)用程序創(chuàng)建的這些greenlet就是通過不斷的拷貝數(shù)據(jù)到heap中或者從heap中拷貝到棧中來實(shí)現(xiàn)并發(fā)的.對于io型的應(yīng)用程序使用coroutine真的非常舒服.
下面是greenlet的一個(gè)簡單的棧空間模型(from greenlet.c)
A PyGreenlet is a range of C stack addresses that must be saved and restored in such a way that the full range of the stack contains valid data when we switch to it. Stack layout for a greenlet: | ^^^ | | older data | | | stack_stop . |_______________| . | | . | greenlet data | . | in stack | . * |_______________| . . _____________ stack_copy + stack_saved . | | | | . | data | |greenlet data| . | unrelated | | saved | . | to | | in heap | stack_start . | this | . . |_____________| stack_copy | greenlet | | | | newer data | | vvv |
下面是一段簡單的greenlet代碼.
from greenlet import greenlet def test1(): print 12 gr2.switch() print 34 def test2(): print 56 gr1.switch() print 78 gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch()
聲明:本網(wǎng)頁內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問題請及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com