Skip to content

Instantly share code, notes, and snippets.

@wycleffsean
Created October 2, 2020 05:32
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 wycleffsean/2ee5bf9f55ab8c70f6e010e6679c77e8 to your computer and use it in GitHub Desktop.
Save wycleffsean/2ee5bf9f55ab8c70f6e010e6679c77e8 to your computer and use it in GitHub Desktop.
Cooperative concurrency in ruby
require 'fiber'
class EventLoop
def initialize
@tasks = {}
@state = {}
end
def call(&block)
instance_eval &block
loop do
@tasks.each { |name, fiber|
unless fiber.alive?
@tasks.delete(name)
next
end
fiber.resume
}
end
end
def task(name, &block)
@tasks[name] = Fiber.new do
instance_eval(&block)
end
end
def set(key, value)
@state[key] ||= []
@state[key] << value
Fiber.yield
end
def get(key, *args)
loop do
return @state[key].pop if @state.key?(key) && @state[key].any?
Fiber.yield
end
end
end
# A cooperatively concurrent restaurant
EventLoop.new.call do
task :open_restaurant do
set(:free_table, 1)
set(:free_table, 2)
end
task :server do
loop do
puts "server - setting table"
table = get(:free_table)
set(:table, table)
puts "server - giving menu"
set(:menu, '...')
puts "server - taking order"
order = get(:order)
puts "server - sending #{order} order to kitchen"
set(:kitchen_order, order)
puts "server - serving #{order}"
order = get(:ready_order)
set(order, order)
end
end
task :chef do
loop do
order = get(:kitchen_order)
puts "chef - making #{order}"
set(:ready_order, order)
end
end
task :customer1 do
puts "customer 1 - waiting for table"
table = get(:table)
puts "customer 1 - waiting for menu"
get(:menu)
puts "customer 1 - ordering"
set(:order, :filet_mignon)
order = get(:filet_mignon)
puts "customer 1 - finished #{order}"
set(:free_table, table)
end
task :customer2 do
puts "customer 2 - waiting for table"
table = get(:table)
puts "customer 2 - waiting for menu"
get(:menu)
puts "customer 2 - ordering"
set(:order, :lobster_bisque)
order = get(:lobster_bisque)
puts "customer 2 - finished #{order}"
set(:free_table, table)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment