require 'thread' class PriorityQueue def initialize (*classes) @order = classes @queues = Hash::new classes.each { |c| @queues[c] = Queue::new } @ilimit = @order.size @waiting = [] end def push (obj) Thread.critical = true begin @queues[obj.class.to_s].push obj t = @waiting.shift t.wakeup if t rescue ThreadError retry rescue NameError raise NameError, "unknown class queue" ensure Thread.critical = false end begin t.run if t rescue ThreadError end end alias << push alias enq push def pop(non_block=false) Thread.critical = true begin loop do i = 0 while (i < @ilimit) and (@queues[@order[i]].empty?) i = i + 1 end if i == @ilimit if non_block raise ThreadError, "queue empty" end @waiting.push Thread.current Thread.stop else return @queues[@order[i]].shift end end ensure Thread.critical = false end end alias shift pop alias deq pop def empty? epty = true @queues.each_value { |q| epty = epty and q.empty? } return epty end def clear @queues.each_value { |q| q.clear } end def length l = 0 @queues.each_value { |q| l += q.length } return l end def size length end def num_waiting @waiting.size end end