Fork threads like Thread.fork, but limit the number of concurrently running threads.
ThreadLimiter isn't a thread pool. Each fork really starts a new thread.
Initialize the ThreadLimiter. The optional parameter limit is the maximum number of concurrently running threads. Set limit to -1 to fork threads without limiting the number of concurrently running threads. Set limit to 0 to join the newly created thread immediately, mimicking no-forking. Set options to true to start the new thread before waiting for resources.
# File lib/threadlimiter/threadlimiter.rb, line 25 def initialize(limit, options={}) @limit = limit # The maximum number of concurrently running threads. @running = 0 # The number of currently running threads. @noblock = options[:noblock] @mutex = Mutex.new @cv = ConditionVariable.new end
Create and use a new ThreadLimiter and wait for all threads to finish.
# File lib/threadlimiter/threadlimiter.rb, line 9 def self.open(*args) thread_limiter = new(*args) begin yield(thread_limiter) ensure thread_limiter.wait end end
Fork a thread. The given block is run within the thread. It behaves like Thread.fork(). In fact, it invokes Thread.fork() and returns its result. The list of arguments is passed to Thread.fork().
# File lib/threadlimiter/threadlimiter.rb, line 40 def fork(*args, &block) if @limit < 0 Thread.fork do yield(*args) end elsif @limit == 0 Thread.fork do yield(*args) end.join # Because ThreadLimiter#fork() should return a new Thread. else cv_wait unless @noblock Thread.fork do cv_wait if @noblock begin yield(*args) ensure cv_signal end end end end
Wait for all threads to finish.
# File lib/threadlimiter/threadlimiter.rb, line 94 def wait @mutex.synchronize do while @running > 0 @cv.wait(@mutex) end end self end