Skip to content

Instantly share code, notes, and snippets.

@careo
Created February 4, 2009 03:27
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 careo/57908 to your computer and use it in GitHub Desktop.
Save careo/57908 to your computer and use it in GitHub Desktop.
Experiments with using fibers with rpc in em
require 'require_me'
def rpc val, &blk
d = EventMachine::DefaultDeferrable.new
d.callback {
blk.call(val)
}
EventMachine.add_timer(0.1) {
d.succeed(val)
}
end
EventMachine.run {
start_time = Time.now
rpc(1) do |rpc_1|
rpc(2) do |rpc_2|
puts rpc_1 + rpc_2
end
end
# just quit after half a sec
EventMachine.add_timer(0.5) {
puts "Total Runtime: #{Time.now - start_time}"
EventMachine.stop
}
}
require 'require_me'
def rpc val
f = Fiber.current
d = EventMachine::DefaultDeferrable.new
d.callback {
f.resume(val)
}
EventMachine.add_timer(0.1) {
d.succeed
}
return Fiber.yield
end
EventMachine.run {
start_time = Time.now
# Note, we've gotta do all the meaty stuff in a fiber I think...
# by "meaty" I mean, everything that we want to ensure happens *synchronously*
Fiber.new {
start = Time.now
result = rpc(1) + rpc(2)
puts "Ran for: #{Time.now - start}"
puts result
}.resume
# just quit after half a sec
EventMachine.add_timer(0.5) {
puts "Total Runtime: #{Time.now - start_time}"
EventMachine.stop
}
}
require 'require_me'
# Shamelessly stolen and (poorly) adapted from mentalguy's lazy.rb lib
class Future
alias __class__ class
alias __send__ send
instance_methods.each { |m| undef_method m unless m =~ /^__/ }
alias class __class__
alias send __send__
def initialize &blk
@f = Fiber.new {
@d = blk.call
if @d.kind_of? EM::DefaultDeferrable
@d.callback { |val|
@f.resume val
}
@d.errback { |val|
@f.resume val
}
else
@result = d
end
@result = Fiber.yield
}
@f.resume
self
end
def method_missing *args, &block
# if we're not quite done yet... then resume the fiber.
if @f.alive?
f = Fiber.current
@d.callback { |val|
f.resume val
}
@result = Fiber.yield
return @result.send(*args, &block)
else
@result
end
end
end
# nice simple asynchronous rpc. takes something to ask for (and eventually gives it back)
# and return a deferrable in case you want to do something else with the result.
def rpc val, &blk
d = EventMachine::DefaultDeferrable.new
EventMachine.add_timer(1) {
d.succeed(val)
}
d
end
EventMachine.run {
start_time = Time.now
# Need to wrap this in a fiber so I can block the whole thing
# in case the value of a future is demanded.
Fiber.new {
start = Time.now
one = Future.new { rpc(1) }
two = Future.new { rpc(2) }
puts "at #{Time.now - start}, about to use futures"
result = one + two
puts "finished with futures at #{Time.now - start}"
puts result
}.resume
# ensure we eventually do quit
EventMachine.add_timer(5) {
puts "Total Runtime: #{Time.now - start_time}"
EventMachine.stop
}
}
require 'rubygems'
require 'eventmachine'
case RUBY_VERSION
when "1.9.1" # stock ruby 1.9.1
require 'fiber'
when "1.8.7" # assume tmm1's patched 1.8.7 with fibers
require 'fiber'
when "1.8.6" # some other poor ruby
require '~/Source/Ruby/fiber18/lib/fiber18'
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment