I know that fibers are cooperative threads. A fiber has control of the execution context, whereas a preemptive thread does not. A fiber can yield control, which means a fiber can start and stop in well-defined places.
Apparently, the reason why fibers are used in evented ruby is to clean up the nested blocks caused by the reactor pattern.
But I have difficulty trying to grasp the control flow of the below script that uses fiber.
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
The way I understand it:
1) EM starts its event loop
2) A fiber is created and then the resume is called. Does the block of code passed to new get executed right away or does it get executed after resume is invoked?
3) http_get is called the first time. It does an asynchronous event (using select, poll or epoll on linux). We set up the event handler (in the callback method) of the asynchronous event. Then Fiber voluntarily yields control to the thread EventMachine is on (the main thread). However, as soon as the callback is invoked, it will take control back with f.resume(http). But in this simplified example, am I supposed to put my own callback code after f.resume(http)? Because right now it seems like f.resume(http) just returns control to the fiber and does nothing else.
I think what happens after yield is the control goes to EventMachine where it enters its event loop. So the second http_get is not invoked yet. Now once the callback is invoked, then control is returned to the Fiber (we only use one Fiber.new so I assume there is only one Fiber instance in all this). But when does the second http_get get called?