class Concurrent::Async::AsyncDelegator

Delegates asynchronous, thread-safe method calls to the wrapped object.

@!visibility private

Public Class Methods

new(delegate) click to toggle source

Create a new delegator object wrapping the given delegate.

@param [Object] delegate the object to wrap and delegate method calls to

Calls superclass method
# File lib/concurrent/async.rb, line 307
def initialize(delegate)
  super()
  @delegate = delegate
  @queue = []
  @executor = Concurrent.global_io_executor
end

Public Instance Methods

method_missing(method, *args, &block) click to toggle source

Delegates method calls to the wrapped object.

@param [Symbol] method the method being called @param [Array] args zero or more arguments to the method

@return [IVar] the result of the method call

@raise [NameError] the object does not respond to `method` method @raise [ArgumentError] the given `args` do not match the arity of `method`

Calls superclass method
# File lib/concurrent/async.rb, line 323
def method_missing(method, *args, &block)
  super unless @delegate.respond_to?(method)
  Async::validate_argc(@delegate, method, *args)

  ivar = Concurrent::IVar.new
  synchronize do
    @queue.push [ivar, method, args, block]
    @executor.post { perform } if @queue.length == 1
  end

  ivar
end
perform() click to toggle source

Perform all enqueued tasks.

This method must be called from within the executor. It must not be called while already running. It will loop until the queue is empty.

# File lib/concurrent/async.rb, line 340
def perform
  loop do
    ivar, method, args, block = synchronize { @queue.first }
    break unless ivar # queue is empty

    begin
      ivar.set(@delegate.send(method, *args, &block))
    rescue => error
      ivar.fail(error)
    end

    synchronize do
      @queue.shift
      return if @queue.empty?
    end
  end
end