57 lines
1.2 KiB
Ruby
57 lines
1.2 KiB
Ruby
|
require 'monitor'
|
||
|
|
||
|
# Basic thread pool with (unlimited) queue
|
||
|
# Based on http://burgestrand.se/code/ruby-thread-pool/
|
||
|
class ThreadPool
|
||
|
|
||
|
def initialize(size, sleep_time=0.1)
|
||
|
@size = size
|
||
|
@sleep_time = sleep_time
|
||
|
@workers_queue = []
|
||
|
@workers_queue.extend(MonitorMixin)
|
||
|
@mutex = @workers_queue.new_cond
|
||
|
|
||
|
@pool = Array.new(@size) do |i|
|
||
|
Thread.new do
|
||
|
Thread.current[:id] = i
|
||
|
catch(:exit) do
|
||
|
loop do
|
||
|
unless @workers_queue.empty?
|
||
|
@workers_queue.synchronize do
|
||
|
@mutex.wait_while { @workers_queue.empty? }
|
||
|
end
|
||
|
job, args = @workers_queue.pop
|
||
|
job.call(*args)
|
||
|
job = nil
|
||
|
args = nil
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
def schedule(*args, &block)
|
||
|
enqueued = false
|
||
|
begin
|
||
|
if @workers_queue.length < @size
|
||
|
@workers_queue.synchronize do
|
||
|
@workers_queue << [block, args]
|
||
|
enqueued = true
|
||
|
@mutex.broadcast
|
||
|
end
|
||
|
else
|
||
|
sleep(@sleep_time)
|
||
|
end
|
||
|
end while (!enqueued)
|
||
|
end
|
||
|
|
||
|
def shutdown
|
||
|
@size.times do
|
||
|
schedule { throw :exit }
|
||
|
end
|
||
|
@pool.map(&:join)
|
||
|
end
|
||
|
|
||
|
end
|