控制红宝石纤维流程
我知道纤维是合作的线程。 光纤具有对执行上下文的控制权,而抢先式线程不具有控制权。 光纤可以产生控制,这意味着光纤可以在明确的位置开始和停止。
显然,为什么光纤用于均匀的红宝石的原因是为了清理由反应堆图案引起的嵌套块。
但是我很难掌握下面使用光纤的脚本的控制流程。
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)创建光纤,然后调用简历。 传递给新获得的代码块是否立即执行,或者是否在调用简历后执行?
3)第一次调用http_get。 它执行一个异步事件(在linux上使用select,poll或epoll)。 我们设置异步事件的事件处理程序(在回调方法中)。 然后光纤自动控制线程EventMachine(主线程)。 但是,只要调用回调函数,它将使用f.resume(http)进行控制。 但在这个简化的例子中,我是否应该在f.resume(http)之后放置自己的回调代码? 因为现在看起来好像f.resume(http)只是将控制权交还给光纤,并且什么都不做。
我认为yield之后会发生什么事情,控制权将进入EventMachine,并进入事件循环。 所以第二个http_get没有被调用。 现在一旦回调被调用,控制就返回到光纤(我们只使用一个Fiber.new,所以我假设在这一切中只有一个光纤实例)。 但是第二个http_get何时被调用?
让我看看我能否为你回答。 我在添加行号来帮助描述:
01: def http_get(url)
02: f = Fiber.current
03: http = EventMachine::HttpRequest.new(url).get
04:
05: # resume fiber once http call is done
06: http.callback { f.resume(http) }
07: http.errback { f.resume(http) }
08:
09: return Fiber.yield
10: end
11:
12: EventMachine.run do
13: Fiber.new{
14: page = http_get('http://www.google.com/')
15: puts "Fetched page: #{page.response_header.status}"
16:
17: if page
18: page = http_get('http://www.google.com/search?q=eventmachine')
19: puts "Fetched page 2: #{page.response_header.status}"
20: end
21: }.resume
22: end
google.come
上进行GET。 在第17行中,它检查是否有来自http_get
有效响应,然后执行第18行中的下一个请求来搜索字符串eventmachine
。 .resume
启动时,第14行被执行,调用http_get
方法。 http
对象的引用,该对象现在在第14行的变量page
中引用,随后在第15行中用于转储HTTP请求状态。 page
是否为真值,然后继续并再次调用http_get
,但使用新的URL。 请注意,代码if page
可能永远不会执行,如果nil
,第15行将在没有检查nil
情况下轰炸访问page
。 希望澄清此事。
至于用额外的逻辑处理HTTP GET的响应,我想你可以用一些有意义的处理逻辑来替换这些puts
。 这个样本中的puts
似乎是处理回复,回调主要用于恢复光纤。
上一篇: control flow in ruby fiber program
下一篇: How does one achieve parallel tasks with Ruby's Fibers?