class Concurrent::Async::AsyncDelegator
Delegates asynchronous, thread-safe method calls to the wrapped object.
@!visibility private
Public Class Methods
Create a new delegator object wrapping the given delegate.
@param [Object] delegate the object to wrap and delegate method calls to
# File lib/concurrent-ruby/concurrent/async.rb, line 288 def initialize(delegate) super() @delegate = delegate @queue = [] @executor = Concurrent.global_io_executor @ruby_pid = $$ end
Public Instance Methods
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`
# 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
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-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
# File lib/concurrent-ruby/concurrent/async.rb, line 348 def reset_if_forked if $$ != @ruby_pid @queue.clear @ruby_pid = $$ end end
Check whether the method is responsive
@param [Symbol] method the method being called
# File lib/concurrent-ruby/concurrent/async.rb, line 322 def respond_to_missing?(method, include_private = false) @delegate.respond_to?(method) || super end