#!/usr/bin/env ruby | |
require 'fiber' | |
require 'benchmark' | |
DEBUG=false | |
class FiberRing | |
attr_reader :id | |
def initialize(id) | |
@id = id | |
DEBUG and puts "Creating ring #{@id}" | |
@fiber = Fiber.new do | |
pass_msg | |
end | |
end | |
def |(nxt) | |
DEBUG and puts "attaching #{@id} to #{nxt.id}" | |
@next = nxt | |
nxt | |
end | |
def resume | |
@fiber.resume | |
end | |
def pass_msg | |
DEBUG and puts "#{@id} pass_msg called" | |
while msg = msg_in | |
DEBUG and puts "#{@id} received \"#{msg}\"" | |
msg_out msg | |
end | |
end | |
def msg_in | |
DEBUG and puts "#{@id} msg_in called" | |
unless @next.nil? | |
DEBUG and puts "#{@id} resuming #{@next.id}" | |
@next.resume | |
DEBUG and puts "#{@id} returned from #{@next.id}.resume" | |
end | |
DEBUG and puts "#{@id} msg_in returning \"#{@id} message\"" | |
"#{@id} message" | |
end | |
def msg_out msg | |
DEBUG and puts "#{@id} msg_out called" | |
DEBUG and puts "#{@id} calling Fiber.yield(#{msg})" | |
Fiber.yield msg | |
end | |
end | |
n=ARGV[0].to_i | |
m=ARGV[1].to_i | |
tm = Benchmark.measure do | |
#build chain | |
f0 = f = FiberRing.new(0) | |
1.upto(n-1) { |i| f = f | FiberRing.new(i) } | |
#run chain m times | |
m.times { |j| DEBUG and puts "--- #{j} ---"; f0.resume } | |
end | |
puts "#{n}, #{m}, #{tm}" |
Bugger! No line numbers. I'll look into that.