class Fibre::FiberPool

Attributes

pool_queue_size[R]
pool_size[R]
queue[R]
reserved[R]

Public Class Methods

new(pool_size: DEFAULT_POOL_SIZE, pool_queue_size: DEFAULT_POOL_QUEUE_SIZE) click to toggle source

Initialize fiber's pool

# File lib/fibre/fiber_pool.rb, line 22
def initialize(pool_size: DEFAULT_POOL_SIZE, pool_queue_size: DEFAULT_POOL_QUEUE_SIZE)
  @pool_size = pool_size
  @pool_queue_size = pool_queue_size
  @reserved = {}
  @queue = []
  @pool = @pool_size.times.collect { ::Fiber.new(&self.method(:fiber_entry)) }
end

Public Instance Methods

checkout(&b) click to toggle source

Borrow fiber from the pool and call the block inside

# File lib/fibre/fiber_pool.rb, line 31
def checkout(&b)
  spec = { block: b, parent: ::Fiber.current }

  if @pool.empty?
    raise "The fiber queue has been overflowed" if @queue.size > @pool_queue_size
    @queue.push spec
    return
  end

  @pool.shift.tap do |fiber|
    @reserved[fiber.object_id] = spec
    fiber.resume(spec)
  end

  self
end

Private Instance Methods

checkin(result=nil) click to toggle source

Return the fiber into the pool

# File lib/fibre/fiber_pool.rb, line 83
def checkin(result=nil)
  @reserved.delete ::Fiber.current.object_id
  @pool.unshift ::Fiber.current
  ::Fiber.yield
end
fiber_entry(spec) click to toggle source

There is entrypoint running fibers

# File lib/fibre/fiber_pool.rb, line 51
def fiber_entry(spec)
  loop do
    raise "wrong spec in fiber block" unless spec.is_a?(Hash)

    begin
      before!(spec)
      spec[:block].call# *Fiber.current.args
      after!(spec)

      # catch ArgumentError, IOError, EOFError, IndexError, LocalJumpError, NameError, NoMethodError
      # RangeError, FloatDomainError, RegexpError, RuntimeError, SecurityError, SystemCallError
      # SystemStackError, ThreadError, TypeError, ZeroDivisionError
    rescue StandardError => e
      if error.empty?
        raise Fibre::FiberError.new(e)
      else
        error!(e)
      end
      # catch NoMemoryError, ScriptError, SignalException, SystemExit, fatal etc
      #rescue Exception
    end

    unless @queue.empty?
      spec = @queue.shift
      next
    end

    spec = checkin
  end
end