From: "Mauricio Fernández" Date: 2003-02-01T10:27:02+09:00 Subject: Re: removing a dead thread On Sat, Feb 01, 2003 at 08:35:24AM +0900, Daniel Bretoi wrote: > Scenario: I have a set of 20 things to do. I can only do 4 things at a > time. > > How can I limit myself to 4 threads? > > This is what I have: > > threads = [] > designs.each { |d| > while threads.size > ARGV[0].to_i > do something? > end > threads << Thread.new(d) { |t| > do stuff... > } > } > > > how would I remove a thread once it's done? > > ideas? This might seem overly complicated but it works, pools your connections/handlers/whatever and is general enough to be reused with little change. (Don't be scared, look at the bottom and see how easy it is to use :) batsman@tux-chan:/tmp$ expand -t 2 c.rb require 'thread' class PooledWhatever def initialize(klass, howmany, args, debug = false) @mutex = Mutex.new @pool = [] @handleravail = ConditionVariable.new howmany.times { @pool << klass.new(*args) } @threads = {} puts "Handler pool: #{@pool.inspect}" if debug end def run(debug = false) ref = [] handler = nil @mutex.synchronize do info = false if @pool.size == 0 @handleravail.wait @mutex info = true if debug end handler = @pool.shift puts "Got handler #{handler} after getting blocked." if info @threads[handler] = ref # hack cause want this # inside synchronize; perhaps not needed end ref << Thread.new do begin yield handler ensure @mutex.synchronize do @pool << handler @threads.delete handler @handleravail.signal end end end end def wait_for_all @threads.each do |handler, thread| thread[0].join end @pool.each { |x| x.close } end def num_tasks @threads.size end end class Dummy def close puts "Closing handler #{self}..." end end runner = PooledWhatever.new(Dummy, 4, [], true) 10.times do |i| runner.run(true) do puts "DOING MAGIC: num threads == #{runner.num_tasks}" sleep ( i.to_f / 20 ) end end runner.wait_for_all batsman@tux-chan:/tmp$ ruby c.rb Handler pool: [#, #, #, #] DOING MAGIC: num threads == 1 DOING MAGIC: num threads == 2 DOING MAGIC: num threads == 2 DOING MAGIC: num threads == 3 DOING MAGIC: num threads == 4 Got handler # after getting blocked. DOING MAGIC: num threads == 4 Got handler # after getting blocked. DOING MAGIC: num threads == 4 Got handler # after getting blocked. DOING MAGIC: num threads == 4 Got handler # after getting blocked. DOING MAGIC: num threads == 4 Got handler # after getting blocked. DOING MAGIC: num threads == 4 Closing handler #... Closing handler #... Closing handler #... Closing handler #... -- _ _ | |__ __ _| |_ ___ _ __ ___ __ _ _ __ | '_ \ / _` | __/ __| '_ ` _ \ / _` | '_ \ | |_) | (_| | |_\__ \ | | | | | (_| | | | | |_.__/ \__,_|\__|___/_| |_| |_|\__,_|_| |_| Running Debian GNU/Linux Sid (unstable) batsman dot geo at yahoo dot com The only "intuitive" interface is the nipple. After that, it's all learned. -- Bruce Ediger, bediger@teal.csn.org, on X interfaces