Skip to content

Instantly share code, notes, and snippets.

@egonSchiele
Created May 16, 2013 18:20

Revisions

  1. egonSchiele created this gist May 16, 2013.
    92 changes: 92 additions & 0 deletions dining_with_waiter.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,92 @@
    require 'thread'

    class Waiter
    def initialize
    @mutex = Mutex.new
    end

    def can_eat? philosopher
    left = philosopher.left_fork
    right = philosopher.right_fork
    @mutex.synchronize do
    if !left.used && !right.used
    left.used = true
    right.used = true
    return true
    else
    return false
    end
    end
    end

    def stop_eating philosopher
    @mutex.synchronize do
    philosopher.left_fork.used = false
    philosopher.right_fork.used = false
    end
    end
    end

    class Philosopher
    attr_accessor :left_fork, :right_fork
    def initialize(name, left_fork, right_fork, waiter)
    @name = name
    @left_fork = left_fork
    @right_fork = right_fork
    @waiter = waiter
    think
    end

    def think
    puts "Philosopher #@name is thinking..."
    sleep(rand())
    puts "Philosopher #@name is hungry..."
    dine
    end

    def dine
    while !@waiter.can_eat?(self)
    think
    end
    puts "Philosopher #@name eats..."
    sleep(rand())
    puts "Philosopher #@name belches"
    @waiter.stop_eating(self)
    think
    end
    end

    n = 5

    forks = []

    class Fork
    attr_accessor :used
    def initialize
    @used = false
    end
    end

    (1..n).each do |i|
    forks << Fork.new
    end

    threads = []
    waiter = Waiter.new

    (1..n).each do |i|
    threads << Thread.new do
    if i < n
    left_fork = forks[i]
    right_fork = forks[i+1]
    else
    # special case for philosopher #5 because he gets forks #5 and #1
    # and the left fork is always the lower id because that's the one we try first.
    left_fork = forks[0]
    right_fork = forks[n]
    end
    Philosopher.new(i, left_fork, right_fork, waiter)
    end
    end

    threads.each {|thread| thread.join}