Skip to content

Instantly share code, notes, and snippets.

@aruprakshit
Forked from toretore/fibers.rb
Created July 7, 2014 04:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aruprakshit/70a43285a337d4eb5b77 to your computer and use it in GitHub Desktop.
Save aruprakshit/70a43285a337d4eb5b77 to your computer and use it in GitHub Desktop.
require 'socket'
require 'fiber'
#A list of readables and writables for IO.select, and which fiber is waiting for which IO
watch = {
readable: {}, #{io => fiber}
writable: {}
}
#Create 5 fibers that asynchronously fetch HTTP from httpbin.org/delay/{1,2,3,4,5}
#httpbin.org/delay will respond after n secs
fibers = 5.times.map do |n|
Fiber.new do
sock = TCPSocket.new('httpbin.org', 80)
#Add the socket to IO.select's writables with this fiber as the watcher
watch[:writable][sock] = Fiber.current
#Yield from this fiber so that other fibers can run while we're waiting
Fiber.yield
#Fiber has now been resumed by the IO loop, and sock is writable
sock.write "GET /delay/#{n} HTTP/1.0\r\nHost: httpbin.org\r\n\r\n"
res = ''
loop do
#Yield until sock is readable
watch[:readable][sock] = Fiber.current
Fiber.yield
if data = sock.read_nonblock(1024) rescue break
res << data
else
break #done reading response
end
end
p res
end
end.each do |f|
f.resume #Start fiber
end
loop do
readables, writables, _ = IO.select watch[:readable].keys, watch[:writable].keys
readables.each do |readable|
if f = watch[:readable].delete(readable)
f.resume(readable)
end
end
writables.each do |writable|
if f = watch[:writable].delete(writable)
f.resume(writable)
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment