71 lines
1.6 KiB
Ruby
71 lines
1.6 KiB
Ruby
require 'mutex_m'
|
|
|
|
class Philosopher
|
|
def initialize(name, left_fork, right_fork)
|
|
@name = name
|
|
@left_fork = left_fork
|
|
@right_fork = right_fork
|
|
@meals = 0
|
|
end
|
|
|
|
def go
|
|
while @meals < 5
|
|
think
|
|
dine
|
|
end
|
|
puts "philosopher #@name is full!"
|
|
end
|
|
|
|
def think
|
|
puts "philosopher #@name is thinking..."
|
|
sleep(rand())
|
|
puts "philosopher #@name is hungry..."
|
|
end
|
|
|
|
def dine
|
|
fork1, fork2 = @left_fork, @right_fork
|
|
while true
|
|
pickup(fork1, :wait => true)
|
|
puts "philosopher #@name has fork #{fork1.fork_id}..."
|
|
if pickup(fork2, :wait => false)
|
|
break
|
|
end
|
|
puts "philosopher #@name cannot pickup second fork #{fork2.fork_id}..."
|
|
release(fork1)
|
|
fork1, fork2 = fork2, fork1
|
|
end
|
|
puts "philosopher #@name has the second fork #{fork2.fork_id}..."
|
|
|
|
puts "philosopher #@name eats..."
|
|
sleep(rand())
|
|
puts "philosopher #@name belches"
|
|
@meals += 1
|
|
|
|
release(@left_fork)
|
|
release(@right_fork)
|
|
end
|
|
|
|
def pickup(fork, opt)
|
|
puts "philosopher #@name attempts to pickup fork #{fork.fork_id}..."
|
|
opt[:wait] ? fork.mutex.mu_lock : fork.mutex.mu_try_lock
|
|
end
|
|
|
|
def release(fork)
|
|
puts "philosopher #@name releases fork #{fork.fork_id}..."
|
|
fork.mutex.unlock
|
|
end
|
|
end
|
|
|
|
n = 5
|
|
|
|
Fork = Struct.new(:fork_id, :mutex)
|
|
forks = Array.new(n) {|i| Fork.new(i, Object.new.extend(Mutex_m))}
|
|
|
|
philosophers = Array.new(n) do |i|
|
|
Thread.new(i, forks[i], forks[(i+1)%n]) do |id, f1, f2|
|
|
ph = Philosopher.new(id, f1, f2).go
|
|
end
|
|
end
|
|
|
|
philosophers.each {|thread| thread.join}
|