Skip to content

Instantly share code, notes, and snippets.

@egonSchiele
Last active September 22, 2018 12:23
Show Gist options
  • Save egonSchiele/5573023 to your computer and use it in GitHub Desktop.
Save egonSchiele/5573023 to your computer and use it in GitHub Desktop.
Dining philosophers in Ruby with Celluloid. Modified from https://gist.github.com/bugant/4984042
require 'rubygems'
require 'celluloid'
class Waiter
include Celluloid
FORK_FREE = 0
FORK_USED = 1
attr_reader :philosophers
attr_reader :forks
attr_reader :eating
def initialize(forks)
@philosophers = []
@eating = []
@forks = Array.new(forks, FORK_FREE)
end
def welcome(philosopher)
@philosophers << philosopher
philosopher.async.think
end
def hungry(philosopher)
pos = @philosophers.index(philosopher)
left_pos = pos
right_pos = (pos + 1) % @forks.size
if @forks[left_pos] == FORK_FREE && @forks[right_pos] == FORK_FREE
@forks[left_pos] = FORK_USED
@forks[right_pos] = FORK_USED
@eating << philosopher
philosopher.async.eat
else
# it's not your turn, keep thinking
philosopher.async.think
end
end
def drop_forks(philosopher)
pos = @philosophers.index(philosopher)
left_pos = pos
right_pos = (pos + 1) % @forks.size
@forks[left_pos] = FORK_FREE
@forks[right_pos] = FORK_FREE
@eating -= [philosopher]
philosopher.async.think
end
end
class Philosopher
include Celluloid
attr_reader :name
attr_reader :waiter
def initialize(name, waiter)
@name = name
@waiter = waiter
waiter.async.welcome(Actor.current)
end
def think
puts "#{name} is thinking"
sleep(rand)
puts "#{name} gets hungry"
waiter.async.hungry(Actor.current)
end
def eat
puts "#{name} is eating"
sleep(rand)
puts "#{name} burps"
waiter.async.drop_forks(Actor.current)
end
end
names = %w{Heraclitus Aristotle Epictetus Schopenhauer Popper}
waiter = Waiter.new(names.size)
philosophers = names.map {|name| Philosopher.new(name, waiter)}
# The main thread is done! Sleep forever
sleep
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment