先記住一句話,子程序是協程的一種特例。html
Python 中的 yield 保存一個 generator 函數的狀態,generator 是一個特殊類型的迭代器(iterator)git
import time def consumer(): r = '' while True: n = yield r print('[CONSUMER] Consuming %s...' % n) time.sleep(1) r = '200 OK' def produce(c): c.next() n = 0 while n < 5: n = n + 1 print('[PRODUCER] Producing %s...' % n) r = c.send(n) print('[PRODUCER] Consumer return: %s' % r) c.close() if __name__=='__main__': c = consumer() produce(c)
運行結果github
[PRODUCER] Producing 1... [CONSUMER] Consuming 1... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 2... [CONSUMER] Consuming 2... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 3... [CONSUMER] Consuming 3... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 4... [CONSUMER] Consuming 4... [PRODUCER] Consumer return: 200 OK [PRODUCER] Producing 5... [CONSUMER] Consuming 5... [PRODUCER] Consumer return: 200 OK
yield 至關於 return,主動交出程序的控制權,只不過它的狀態保存到了內存中,還會再把控制權要回來的。第一次調用 consumer().next() 時會運行到 consumer 的 yield 這一行,而後權限又跑到了 producer 中。運行到 producer send 這一行,把權限給 consumer。consumer 和 producer 之間經過 yield 和 send 輪換掌握控制權。這樣就實現了非線程方式的搶佔式多任務。微信
next() 和 send() 調用是同樣的,next() 不能傳參數。網絡
libco 代碼見 github,支持的功能框架
1.協程的建立與調度,使用 co_create,co_resume,co_yield 來搭建協程服務。和 Python 的 yield 方式很相似異步
2.基於網絡的協程調度框架,能夠經過網絡事件來進行協程調度函數
libco 能夠將系統的同步操做異步化,如標準 read 函數讀取文件,系統打開文件描述符,阻塞在這裏,一旦讀取完畢返回。異步化就是調用 read 後直接返回,設置一個函數來處理讀取完畢後返回的數據。把事件(讀取完數據)注入到 epoll 中,同時 yield 交出線程控制權,一旦事件到來,切換到這個協程進行處理。ui
經過 hack 的方式替換掉了 read 函數,同理也能夠替換掉和網絡讀寫有關的接口,這樣能夠適用於 RPC 框架,這就是 libco 的主要思想。.net