class ThreadLimiter

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.

Constants

VERSION

Public Class Methods

new(limit, options={}) click to toggle source

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
open(*args) { |thread_limiter| ... } click to toggle source

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

Public Instance Methods

fork(*args) { |*args| ... } click to toggle source

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() click to toggle source

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