之前看的greenlet只是提供了基本的coroutine的作用,是最小的执行单元.但是要想使用,还需要提供一个调度器,来调度什么时候哪些greenlet应该执行.所以看了一下gevent的实现,当前的稳定版本使用的是libev.libevent的一种替代方案.性能上更优越一些.libev支持很多事件类型,但是最常用的是io和timer类型的.io类型的通过系统提供的相关系统调用实现(linux下是epoll),timer类型的通过维护一个最小堆实现.
看一下下面的代码:
Python代码
import gevent from gevent import monkey monkey.patch_all() def download(): import urllib2 urllib2.urlopen('http://www.google.com/').read() c = gevent.spawn(download) gevent.joinall([c])
登录后复制
gevent通过spawn创建并启动一个greenlet,此greenlet执行函数为download.启动这个greenlet是通过把这个greenlet加入到libev的prepare callback里面.libev在每次执行事件循环的时候都会调用prepare callback里面的函数,执行后把里面的callback清除掉.这样就能保证每次spawn的greenlet有执行的机会.并且只会执行一次.
在这个greenlet执行urlopen以及read的时候,因为涉及到io操作(socket.[send|recv]),gevent通过monkey patch把这些函数进行了封装,当调用相关的操作时就会创建一个对应fd的watcher加入到libev的事件列表里面.
当有相关的读写事件发生时,会触发相应的callback.相关的callback会调用greenlet的switch进行coroutine的切换.
通过上面的方式greenlet达到了调度器的目的.
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。
发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2281594.html