Sha256: e26bd26c4003f33eabeb512258bb95a53f09b97e027e75d36e08461bce32cb02

Contents?: true

Size: 1.1 KB

Versions: 5

Compression:

Stored size: 1.1 KB

Contents

# frozen_string_literal: true

export_default :ResourcePool

# Implements a limited resource pool
class ResourcePool
  # Initializes a new resource pool
  # @param opts [Hash] options
  # @param &block [Proc] allocator block
  def initialize(opts, &block)
    @allocator = block

    @available = []
    @waiting = []

    @limit = opts[:limit] || 4
    @count = 0
  end

  def acquire
    resource = wait
    yield resource
  ensure
    @available << resource if resource
    dequeue unless @waiting.empty?
  end

  def wait
    fiber = Fiber.current
    @waiting << fiber
    dequeue
    suspend
  ensure
    @waiting.delete(fiber)
  end

  def dequeue
    return unless (resource = from_stock)
    EV.next_tick { @waiting[0]&.transfer(resource) }
  end

  def from_stock
    @available.shift || (@count < @limit && allocate)
  end

  def method_missing(sym, *args, &block)
    acquire { |r| r.send(sym, *args, &block) }
  end

  # Allocates a resource
  # @return [any] allocated resource
  def allocate
    @count += 1
    @allocator.()
  end

  def preheat!
    (@limit - @count).times { @available << from_stock }
  end
end

Version data entries

5 entries across 5 versions & 1 rubygems

Version Path
polyphony-0.19 lib/polyphony/core/resource_pool.rb
polyphony-0.17 lib/polyphony/core/resource_pool.rb
polyphony-0.16 lib/polyphony/core/resource_pool.rb
polyphony-0.15 lib/polyphony/resource_pool.rb
polyphony-0.14 lib/polyphony/resource_pool.rb