# # The Dining Philosophers - thread example # require "xlib" require "thread" include Xlib include Math $dis = Display.new $white = $dis.alloc_color 'white' $win = $dis.root.new_window 320,320,nil,true $win.pixel = $white $gc = $win.new_gc $win.title = 'The Dining Philosophers - thread example' $win.show $color = { 'none' => 'blue' , 'eat' => 'red' , } $color.each { |key, value| $color[key] = $dis.alloc_color value } PHILOS_SIZE = 32 class << $gc def draw_philos(n, act) angle = 2*PI*n/N x = cos(angle) * $win.width * 0.4 + $win.width / 2 y = sin(angle) * $win.height * 0.4 + $win.height / 2 r = PHILOS_SIZE area = Rect.new((x-r/2).to_i, (y-r/2).to_i, r, r) $gc.fg = $color[act] $gc.fill_oval area, 0, 360*64 end end srand N=9 # number of philosophers $forks = [] $eat_p = [] for i in 0..N-1 $forks[i] = Mutex.new $eat_p[i] = false end def redraw for i in 0..N-1 $gc.draw_philos i, if $eat_p[i] then 'eat' else 'none' end end end redraw $dis.flush def wait sleep rand(20)/10.0 end def think(n) wait end def eat(n) $gc.draw_philos n, 'eat' $eat_p[n] = true wait $eat_p[n] = false $gc.draw_philos n, 'none' end def philosopher(n) while TRUE think n $forks[n].lock if not $forks[(n+1)%N].try_lock $forks[n].unlock # avoid deadlock next end eat n $forks[n].unlock $forks[(n+1)%N].unlock end end $win.event 'exposed' do redraw; end for i in 0..N-1 Thread.start{philosopher(i)} sleep 0.1 end while $dis.event; $dis.sync; end