【发布时间】:2016-09-16 22:04:37
【问题描述】:
我知道纤维是协作线程。纤程可以控制执行上下文,而抢占式线程则不能。光纤可以产生控制,这意味着光纤可以在明确定义的位置开始和停止。
显然,在 evented 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) 创建一个纤程,然后调用恢复。传递给 new 的代码块是立即执行还是在调用 resume 后执行?
3) http_get 被第一次调用。它执行异步事件(在 linux 上使用 select、poll 或 epoll)。我们设置了异步事件的事件处理程序(在回调方法中)。然后 Fiber 自愿将控制权交给 EventMachine 所在的线程(主线程)。但是,一旦调用回调,它将通过 f.resume(http) 收回控制权。但是在这个简化的例子中,我应该把我自己的回调代码放在 f.resume(http) 之后吗?因为现在看起来 f.resume(http) 只是将控制权返回给 Fiber 而没有做任何其他事情。
我认为在 yield 之后发生的事情是控件转到 EventMachine 并进入其事件循环。所以第二个 http_get 还没有被调用。现在一旦调用回调,控制权就会返回给 Fiber(我们只使用一个 Fiber.new,所以我假设所有这些中只有一个 Fiber 实例)。但是第二个 http_get 什么时候被调用呢?
【问题讨论】:
-
自我注意:创建光纤时,它不会自动运行。相反,必须明确要求它使用 Fiber#resume 方法运行。