我知道纤程是协作线程。一个纤程控制着执行上下文,而抢占式线程则不是这样。一个纤程可以放弃控制权,也就是说,一个纤程可以在定义明确的地方开始和停止。
显然,在事件驱动的 Ruby 中使用纤程的原因是为了清理由反应器模式引起的嵌套块。
但我很难理解下面使用纤程的脚本的控制流程。
def http_get(url)
f = Fiber.current
http = EventMachine::HttpRequest.new(url).get
# resume fiber once http call is done
http.callback { f.resume(http) }
http.errback { f.resume(http) }
return Fiber.yield
end
EventMachine.run do
Fiber.new{
page = http_get('http://www.google.com/')
puts "Fetched page: #{page.response_header.status}"
if page
page = http_get('http://www.google.com/search?q=eventmachine')
puts "Fetched page 2: #{page.response_header.status}"
end
}.resume
end
我理解的方式如下:
1)EM启动其事件循环。
2)创建纤维,然后调用resume。传递给new的代码块是立即执行还是在调用resume之后执行?
3)第一次调用http_get。它使用异步事件(在Linux上使用select、poll或epoll)。我们设置异步事件的事件处理程序(在回调方法中)。然后Fiber自愿将控制权交给线程EventMachine所在的线程(主线程)。但是,一旦回调被调用,它就会使用f.resume(http)重新获得控制权。但在这个简化的例子中,我应该在f.resume(http)之后放置自己的回调代码吗?因为现在看起来f.resume(http)只是返回控制权到纤维并没有做其他事情。
我认为在yield之后控制流转到EventMachine,然后进入其事件循环中。所以第二个http_get还没有被调用。现在一旦回调被调用,控制就会返回到Fiber(我们只使用一个Fiber.new,所以我假设在所有这些中只有一个Fiber实例)。但第二个http_get何时被调用?