-
-
Save rkh/2037092 to your computer and use it in GitHub Desktop.
require 'thread' | |
class Worker | |
def initialize(count = 1) | |
@queue, @closing, @threads, @mutex = Queue.new, false, [], Mutex.new | |
add_worker(count) | |
end | |
def add_worker(count = 1) | |
@mutex.synchronize do | |
@threads += count.times.map { Thread.new { @queue.pop.call until @closing } } | |
end | |
end | |
def run(block = Proc.new) | |
@queue << block | |
end | |
def close(&block) | |
run do | |
@closing = true | |
yield if block_given? | |
wakeup | |
end | |
end | |
def join | |
@threads.each(&:join) | |
end | |
private | |
def wakeup | |
run { wakeup if @queue.num_waiting > 0 } | |
end | |
end |
right
If you have more than one worker, only one of them will shutdown, as the @closing
will only be set once. You probably need to remember your worker threads and schedule close
on each of them directly (or at least schedule close
worker_threads.count
times.
No, @closing
is local to the worker instance which can launch more than one thread, but it will be true
in all threads.
Meh, of course... But then I wouldn't call @queue.clear
to have something like a soft-stop and to not lose already scheduled jobs.
But that rather depends on your use case.
I have an old piece of code that looks awfully similar to this, but uses throw/catch instead of the @closing thing: http://burgestrand.se/code/ruby-thread-pool/thread-pool.rb (I partly did it as an experiment with rocco)
It does not support adding more workers, however.
Wouldn't it be better to do something like this to make sure the block is called?