Module: Concurrent::Async

Defined in:
lib/concurrent/async.rb

Overview

See Also:

Since:

  • 0.6.0

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.validate_argc(obj, method, *args) ⇒ Object

Note:

This check is imperfect because of the way Ruby reports the arity of methods with a variable number of arguments. It is possible to determine if too few arguments are given but impossible to determine if too many arguments are given. This check may also fail to recognize dynamic behavior of the object, such as methods simulated with ‘method_missing`.

Check for the presence of a method on an object and determine if a given set of arguments matches the required arity.

Parameters:

  • obj (Object)

    the object to check against

  • method (Symbol)

    the method to check the object for

  • args (Array)

    zero or more arguments for the arity check

Raises:

  • (NameError)

    the object does not respond to ‘method` method

  • (ArgumentError)

    the given ‘args` do not match the arity of `method`

See Also:

Since:

  • 0.6.0



37
38
39
40
41
42
43
44
45
46
# File 'lib/concurrent/async.rb', line 37

def validate_argc(obj, method, *args)
  argc = args.length
  arity = obj.method(method).arity

  if arity >= 0 && argc != arity
    raise ArgumentError.new("wrong number of arguments (#{argc} for #{arity})")
  elsif arity < 0 && (arity = (arity + 1).abs) > argc
    raise ArgumentError.new("wrong number of arguments (#{argc} for #{arity}..*)")
  end
end

Instance Method Details

#asyncConcurrent::IVar Also known as: future

Note:

The method call is guaranteed to be thread safe with respect to all other method calls against the same object that are called with either ‘async` or `await`. The mutable nature of Ruby references (and object orientation in general) prevent any other thread safety guarantees. Do NOT mix non-protected method calls with protected method call. Use only protected method calls when sharing the object between threads.

Causes the chained method call to be performed asynchronously on the global thread pool. The method called by this method will return a future object in the ‘:pending` state and the method call will have been scheduled on the global thread pool. The final disposition of the method call can be obtained by inspecting the returned future.

Before scheduling the method on the global thread pool a best-effort attempt will be made to validate that the method exists on the object and that the given arguments match the arity of the requested function. Due to the dynamic nature of Ruby and limitations of its reflection library, some edge cases will be missed. For more information see the documentation for the ‘validate_argc` method.

Returns:

Raises:

  • (Concurrent::InitializationError)

    ‘#init_mutex` has not been called

  • (NameError)

    the object does not respond to ‘method` method

  • (ArgumentError)

    the given ‘args` do not match the arity of `method`

See Also:

Since:

  • 0.6.0



133
134
135
136
# File 'lib/concurrent/async.rb', line 133

def async
  raise InitializationError.new('#init_mutex was never called') unless @__async_initialized__
  @__async_delegator__.value
end

#awaitConcurrent::IVar Also known as: delay

Note:

The method call is guaranteed to be thread safe with respect to all other method calls against the same object that are called with either ‘async` or `await`. The mutable nature of Ruby references (and object orientation in general) prevent any other thread safety guarantees. Do NOT mix non-protected method calls with protected method call. Use only protected method calls when sharing the object between threads.

Causes the chained method call to be performed synchronously on the current thread. The method called by this method will return an ‘IVar` object in either the `:fulfilled` or `rejected` state and the method call will have completed. The final disposition of the method call can be obtained by inspecting the returned `IVar`.

Before scheduling the method on the global thread pool a best-effort attempt will be made to validate that the method exists on the object and that the given arguments match the arity of the requested function. Due to the dynamic nature of Ruby and limitations of its reflection library, some edge cases will be missed. For more information see the documentation for the ‘validate_argc` method.

Returns:

Raises:

  • (Concurrent::InitializationError)

    ‘#init_mutex` has not been called

  • (NameError)

    the object does not respond to ‘method` method

  • (ArgumentError)

    the given ‘args` do not match the arity of `method`

See Also:

Since:

  • 0.6.0



167
168
169
170
# File 'lib/concurrent/async.rb', line 167

def await
  raise InitializationError.new('#init_mutex was never called') unless @__async_initialized__
  @__await_delegator__.value
end

#executor=(executor) ⇒ Object

Set a new executor

Raises:

Since:

  • 0.6.0



177
178
179
180
181
# File 'lib/concurrent/async.rb', line 177

def executor=(executor)
  raise InitializationError.new('#init_mutex was never called') unless @__async_initialized__
  @__async_executor__.reconfigure { executor } or
    raise ArgumentError.new('executor has already been set')
end

#init_mutexObject

Note:

This method must be called from the constructor of the including class or explicitly by the caller prior to calling any other methods. This is the only way thread-safe initialization can be guaranteed.

Initialize the internal serializer and other synchronization objects. This method must be called from the constructor of the including class or explicitly by the caller prior to calling any other methods. If ‘init_mutex` is not called explicitly the async/await/executor methods will raize a `Concurrent::InitializationError`. This is the only way thread-safe initialization can be guaranteed.

Raises:

Since:

  • 0.6.0



195
196
197
198
199
200
201
202
203
204
# File 'lib/concurrent/async.rb', line 195

def init_mutex
  raise InitializationError.new('#init_mutex was already called') if @__async_initialized__
  @__async_initialized__ = true
  serializer = Concurrent::SerializedExecution.new
  @__async_executor__ = Delay.new{ Concurrent.configuration.global_operation_pool }
  @__await_delegator__ = Delay.new{ AsyncDelegator.new(
    self, Delay.new{ Concurrent::ImmediateExecutor.new }, serializer, true) }
  @__async_delegator__ = Delay.new{ AsyncDelegator.new(
    self, @__async_executor__, serializer, false) }
end