先记住一句话,子程序是协程的一种特例。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