Created
June 20, 2012 18:02
-
-
Save seanlilmateus/2961258 to your computer and use it in GitHub Desktop.
Macruby and Rubymotion GCD Semaphore example (The Dining Philosophers Problem)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env macruby -wKU | |
class Philosopher | |
def initialize(name, left_chopstick, right_chopstick) | |
@name = name | |
@left_chopstick = left_chopstick | |
@right_chopstick = right_chopstick | |
@meals = 0 | |
end | |
def run | |
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 | |
chopstick1, chopstick2 = @left_chopstick, @right_chopstick | |
while true | |
pickup(chopstick1, :wait => true) | |
puts "philosopher: #@name has chopstick #{chopstick1.id}..." | |
break if pickup(chopstick2, :wait => false) | |
puts "philosopher: #@name cannot pickup second chopstick #{chopstick2.id}..." | |
release(chopstick1) | |
chopstick1, chopstick2 = chopstick2, chopstick1 | |
end | |
puts "philosopher: #@name has the second chopstick #{chopstick2.id}..." | |
puts "philosopher: #@name eats..." | |
sleep(rand()) | |
puts "philosopher: #@name belches" | |
@meals += 1 | |
release(@left_chopstick) | |
release(@right_chopstick) | |
end | |
def pickup(chopstick, opt) | |
puts "philosopher: #@name attempts to pickup chopstick #{chopstick.id}..." | |
chopstick.wait(opt) | |
end | |
def release(chopstick) | |
puts "philosopher: #@name releases chopstick #{chopstick.id}..." | |
chopstick.release | |
end | |
end | |
# we just wrappe the semaphores | |
class Chopstick < Struct.new(:id, :semaphore) | |
def release | |
semaphore.signal | |
end | |
def wait(opt={}) | |
semaphore.wait(opt[:wait] ? Dispatch::TIME_FOREVER : Dispatch::TIME_NOW) | |
end | |
end | |
philosophers = %W{Aristotle Kant Spinoza Marx Russell} | |
size = philosophers.length | |
chopsticks = Array.new(size) { |i| Chopstick.new(i+1, Dispatch::Semaphore.new(1)) } | |
queue = Dispatch::Queue.concurrent("de.mateus.philosophers.problem") | |
group = Dispatch::Group.new | |
philosophers.each_with_index do |name, idx| | |
queue.async(group) do | |
cs1 = chopsticks[idx] | |
cs2 = chopsticks[(idx+1)%size] | |
Philosopher.new(name, cs1, cs2).run | |
end | |
end | |
# since we want to see the out put, he have to wait till all the dispatch tasks are done | |
group.wait |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment