Hi Eric On Mon, 2005-08-29 at 19:09, Eric Hodel wrote: > On 29 Aug 2005, at 08:57, Andrew S. Townley wrote: [snip] > ThreadGroup, ThreadGroup, ThreadGroup. Create a ThreadGroup for each > thread you spawn so you can see who is spawning the extra threads. Hmmm... I think I might use a ThreadGroup, no? ;) > > Also, I've looked at this from a number of different angles, but it > > appears to be no way to create a normal thread pool with Ruby. Ok, this was just selective stupidity on my part. Apologies. After digging out my Doug Lea Concurrent Java book, I saw what I was forgetting... > What do you want? Something like this (actually, it was straightforward enough once I thought about it a little): $ cat tpool.rb require 'thread' class ThreadPool def initialize(size) @work = Queue.new @workers = [] @group = ThreadGroup.new @shutdown = false @sh_mutex = Mutex.new size.times do @workers << t = Thread.new { Thread.stop; thread_work }; @group.add(t) end @monitor = Thread.new do Thread.stop loop do @sh_mutex.synchronize { Thread.current.terminate if @shutdown } sleep(1) end end end def <<(runnable) @work << runnable self end def thread_work loop do @sh_mutex.synchronize do if @shutdown puts "#{Thread.current} stopping"; Thread.current.terminate end end puts "#{Thread.current.inspect} is one of #{@work.num_waiting} waiting for work" job = @work.deq begin job.run if job != nil Thread.pass rescue => e puts e next end end end def start @workers.each { |w| w.run } @monitor.run end def join @monitor.join end def shutdown(wait = true) @sh_mutex.synchronize { @shutdown = true } @workers.each { |w| w.join if w.alive? } if wait end attr_reader :group end class Runnable def initialize(*args, &block) @block = block end def run @block.call end end pool = ThreadPool.new(8) pool.start job1 = Runnable.new do 3.times { puts "#{Thread.current.inspect} - hello"; sleep(rand*3) } end vagrant = Runnable.new { raise "broken" } pool << job1 << vagrant << job1 << job1 << job1 << job1 pool << vagrant << job1 << job1 << vagrant << vagrant << job1 Thread.new { t = rand*2; puts "sleeping #{t}"; sleep(t); pool.shutdown(false) } pool.join pool.shutdown puts "Thread group" pool.group.list.each { |w| puts w.inspect } puts "Thread.list" Thread.list.each { |w| puts w.inspect } *************************************************************************************************** The information in this email is confidential and may be legally privileged. Access to this email by anyone other than the intended addressee is unauthorized. If you are not the intended recipient of this message, any review, disclosure, copying, distribution, retention, or any action taken or omitted to be taken in reliance on it is prohibited and may be unlawful. If you are not the intended recipient, please reply to or forward a copy of this message to the sender and delete the message, any attachments, and any copies thereof from your system. ***************************************************************************************************