Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Dining Philosophers solution using Celluloid
#!/usr/bin/env ruby
require 'rubygems'
require 'bundler/setup'
require 'celluloid'
class Table
include Celluloid
CHOPSTICK_FREE = 0
CHOPSTICK_USED = 1
attr_reader :philosophers
attr_reader :chopsticks
attr_reader :eating
def initialize(chopsticks)
@philosophers = []
@eating = []
@chopsticks = Array.new(chopsticks, CHOPSTICK_FREE)
end
def welcome(philosopher)
@philosophers << philosopher
philosopher.async.think
end
def hungry(philosopher)
pos = @philosophers.index(philosopher)
abort RuntimeError.new('A philosopher is not even sat down') if pos.nil?
left_pos = pos
right_pos = (pos + 1) % @chopsticks.size
if [@chopsticks[left_pos], @chopsticks[right_pos]].all? {|status| status == CHOPSTICK_FREE}
@chopsticks[left_pos] = CHOPSTICK_USED
@chopsticks[right_pos] = CHOPSTICK_USED
@eating << philosopher
print_table_status(pos)
philosopher.async.eat
abort RuntimeError.new('TOO MANY PHILOSOPHER ARE EATING') if @eating.size == @chopsticks.size
puts "TABLE: #{@eating.size} are eating"
else
# it's not your turn, keep thinking
print_table_status(pos)
philosopher.async.think
end
end
def drop_chopsticks(philosopher)
pos = @philosophers.index(philosopher)
abort RuntimeError.new('A philosopher is not even sat down') if pos.nil?
left_pos = pos
right_pos = (pos + 1) % @chopsticks.size
if ! [@chopsticks[left_pos], @chopsticks[right_pos]].all? {|status| status == CHOPSTICK_USED}
abort RuntimeError.new('A philosopher without both chopsticks thinks he had eaten')
end
@chopsticks[left_pos] = CHOPSTICK_FREE
@chopsticks[right_pos] = CHOPSTICK_FREE
@eating -= [philosopher]
print_table_status(pos)
philosopher.async.think
end
def print_table_status(pos)
puts "TABLE: EATING: #{eating.map {|p| philosophers.index(p)}}; CHOPSTICKS #{chopsticks}; MY POS: #{pos}"
end
end
class Philosopher
include Celluloid
attr_reader :name
attr_reader :table
def initialize(name, table)
@name = name
@table = table
table.async.welcome(Actor.current)
end
def think
puts "#{name} is thinking"
sleep(rand)
puts "#{name} gets hungry"
table.async.hungry(Actor.current)
end
def eat
puts "#{name} is eating"
sleep(rand)
puts "#{name} burps"
table.async.drop_chopsticks(Actor.current)
end
end
#
# Run the simulation
#
names = %w{Heraclitus Aristotle Epictetus Schopenhauer Popper}
table = Table.new(names.size)
philosophers = names.map {|name| Philosopher.new(name, table)}
# 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
You can’t perform that action at this time.