2016-09-16 60 views
2

我知道纖維是合作的線程。光纖具有對執行上下文的控制權,而搶先式線程不具有控制權。光纖可以產生控制,這意味着光纖可以在明確的位置開始和停止。紅寶石纖維程序控制流程

很明顯,爲什麼纖維用於均勻的紅寶石的原因是清理由反應堆模式引起的嵌套塊。

但是我很難掌握下面使用光纖的腳本的控制流。

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何時被調用?

+0

自我注意:創建光纖時,它不會自動運行。相反,必須明確要求使用光纖#恢復方法運行。 – Donato

回答

0

讓我看看我能否爲你解答。我添加行號,以幫助說明:

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 
  1. 線21開始光纖,其代碼在14-20行
  2. 纖維代碼似乎是在做下面的執行:行14個檢查是否我們可以在google.come上做GET。在第17行中,它檢查是否有來自http_get的有效響應,然後執行第18行中的下一個請求以搜索字符串eventmachine
  3. 當第21行的.resume由於.resume開始執行光纖時,將執行第14行調用http_get方法。
  4. 02行到07行設置異步HTTP GET請求和回調。
  5. 09行將控制權返回給EventMachine。
  6. 經過一段時間,來自線路03的異步HTTP GET調用異步完成執行並導致線路06或07上的回調之一後,在線路13到線路20上創建的原始光纖恢復控制。
  7. 現在光纖執行從第15行重新開始。第06/07行的回調已通過對http對象的引用,該對象現在在第14行中用變量page引用,隨後在第15行中用於轉儲HTTP請求狀態。
  8. 隨着光纖繼續執行進一步,它會檢查page是否爲真值,然後繼續並再次調用http_get,但使用新的URL。請注意,如果代碼爲nil,代碼if page可能永遠不會執行,因爲第15行將會在沒有nil的檢查的情況下訪問page而被訪問。
  9. 類似的過程重複 - 02至07行設置HTTP GET調用,09行將控制權返回給EventMachine。
  10. 經過一段時間後,調用其中一個回調,並在光纖重新獲得控制時執行第19行。
  11. 執行第19行後,光纖將會死亡。

希望澄清此事。

至於用額外的邏輯處理HTTP GET的響應,我想你可以用一些有意義的處理邏輯替代puts。本示例中的puts似乎是處理響應,回調主要用於恢復光纖。