switch函数——Gevent源码分析
在gevent的源码中,经常能看到switch函数。而不同的类中的switch函数有不同的用法
1. greenlet的switch函数
这里面的greenlet是greenlet库中的greenlet类,它是gevent中的Greenlet类的基类(即Greenlet类是在greenlet类的基础之上的扩展)
在这个基类里面,它的switch函数的作用是:切换到这个greenlet协程中,并执行该协程的任务
- 如果这个协程的任务并没有被激活过,则执行
self.run
函数来执行这个协程的任务 - 如果已经被激活,而且正在运行这个协程的任务(即在执行run函数的时候切到了另一个协程中),调用switch函数将回到这个协程的状态(即上次运行的地点)
2. hub的switch函数
首先,主协程hub类继承了greenlet库的greenlet类。下面是hub的switch函数源码:
def switch(self):
switch_out = getattr(getcurrent(), 'switch_out', None)
if switch_out is not None:
switch_out()
return greenlet.switch(self)
return greenlet.switch(self)
这句说明了这个switch函数将返回greenlet类的switch方法(也就是第一类switch,分两种情况: 执行过要切换的协程的run函数,和未执行run),从而实现切换到子协程并执行其任务的作用(即在hub实现协程的切换)
3. Waiter的switch函数
Waiter的switch函数只能被主协程hub调用
以下是switch的源码:
def switch(self, value=None):
"""Switch to the greenlet if one's available. Otherwise store the value."""
greenlet = self.greenlet
if greenlet is None:
self.value = value
self._exception = None
else:
assert getcurrent() is self.hub, "Can only use Waiter.switch method from the Hub greenlet"
switch = greenlet.switch
try:
switch(value)
except:
self.hub.handle_error(switch, *sys.exc_info())
这个switch的作用是切换到可用的协程greenlet的上次执行的地点和状态(也就是上面第一种switch被调用的时候,这个协程已经执行了run函数,则回到上次执行的状态,继续执行),否则就保存value值