123456789_123456789_123456789_123456789_123456789_

Class: Concurrent::Async::AsyncDelegator

Relationships & Source Files
Super Chains via Extension / Inclusion / Inheritance
Class Chain:
Instance Chain:
Inherits: Concurrent::Synchronization::LockableObject
Defined in: lib/concurrent-ruby/concurrent/async.rb

Overview

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

Class Method Summary

Instance Method Summary

Synchronization::LockableObject - Inherited

Constructor Details

.new(delegate) ⇒ AsyncDelegator

Create a new delegator object wrapping the given delegate.

Parameters:

  • delegate (Object)

    the object to wrap and delegate method calls to

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/async.rb', line 288

def initialize(delegate)
  super()
  @delegate = delegate
  @queue = []
  @executor = Concurrent.global_io_executor
  @ruby_pid = $$
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ IVar

Delegates method calls to the wrapped object.

Parameters:

  • method (Symbol)

    the method being called

  • args (Array)

    zero or more arguments to the method

Returns:

  • (IVar)

    the result of the method call

Raises:

  • (NameError)

    the object does not respond to method method

  • (ArgumentError)

    the given args do not match the arity of method

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/async.rb', line 305

def method_missing(method, *args, &block)
  super unless @delegate.respond_to?(method)
  Async::validate_argc(@delegate, method, *args)

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

  ivar
end

Instance Method Details

#perform

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.

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/async.rb', line 330

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

#reset_if_forked

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/async.rb', line 348

def reset_if_forked
  if $$ != @ruby_pid
    @queue.clear
    @ruby_pid = $$
  end
end

#respond_to_missing?(method, include_private = false) ⇒ Boolean

Check whether the method is responsive

Parameters:

  • method (Symbol)

    the method being called

[ GitHub ]

  
# File 'lib/concurrent-ruby/concurrent/async.rb', line 322

def respond_to_missing?(method, include_private = false)
  @delegate.respond_to?(method) || super
end