class Concurrent::Delay

@see Concurrent::Concern::Dereferenceable
execute on the given executor, allowing the call to timeout.
constructor option. This will cause the delayed operation to be
irrelevant. To enable non-blocking behavior, use the ‘executor`
the current thread. This makes the `timeout` value completely
calling either `value` or `wait`, executing the delayed operation on
@note The default behavior of `Delay` is to block indefinitely when
@!macro delay_note_regarding_blocking
@!macro copy_options
safety of the reference returned by `#value`.
`Delay` includes the `Concurrent::Concern::Dereferenceable` mixin to support thread
any side effects created by the operation will only happen once as well.
return the cached value. The operation will only be run once. This means that
blocked on `#value` will return. Subsequent calls to `#value` will immediately
reason will be set to the raised exception, as appropriate. All threads
is complete the value will be set to the result of the operation or the
threads attempting to call `#value` will block as well. Once the operation
enclosed opration will be run and the calling thread will block. Other
reason are both `nil`. The first time the `#value` method is called the
When a `Delay` is created its state is set to `pending`. The value and
with a timeout.
the block execute asynchronously, block indefinitely, or block
At that time the caller can choose to return immediately and let
block will be deferred until the first time `#value` is called.
custom executor upon which to execute the block. Processing of
supports the `Concern::Obligation` interface, and accepts the injection of
expensive operations that may never be needed. It may be non-blocking,
Lazy evaluation of a block yielding an immutable result. Useful for

def execute_task_once # :nodoc:

:nodoc:
@!visibility private
def execute_task_once # :nodoc:
  # this function has been optimized for performance and
  # should not be modified without running new benchmarks
  execute = task = nil
  synchronize do
    execute = @evaluation_started = true unless @evaluation_started
    task    = @task
  end
  if execute
    executor = Options.executor_from_options(executor: @executor)
    executor.post do
      begin
        result  = task.call
        success = true
      rescue => ex
        reason = ex
      end
      synchronize do
        set_state(success, result, reason)
        event.set
      end
    end
  end
end

def initialize(opts = {}, &block)

Raises:
  • (ArgumentError) - if no block is given

Other tags:
    Yield: - the delayed operation to perform
def initialize(opts = {}, &block)
  raise ArgumentError.new('no block given') unless block_given?
  super(&nil)
  synchronize { ns_initialize(opts, &block) }
end

def ns_initialize(opts, &block)

def ns_initialize(opts, &block)
  init_obligation
  set_deref_options(opts)
  @executor = opts[:executor]
  @task               = block
  @state              = :pending
  @evaluation_started = false
end

def reconfigure(&block)

Returns:
  • (true, false) - if success

Other tags:
    Yield: - the delayed operation to perform
def reconfigure(&block)
  synchronize do
    raise ArgumentError.new('no block given') unless block_given?
    unless @evaluation_started
      @task = block
      true
    else
      false
    end
  end
end

def value(timeout = nil)

Returns:
  • (Object) - the current value of the object

Parameters:
  • timeout (Numeric) -- the maximum number of seconds to wait
def value(timeout = nil)
  if @executor # TODO (pitr 12-Sep-2015): broken unsafe read?
    super
  else
    # this function has been optimized for performance and
    # should not be modified without running new benchmarks
    synchronize do
      execute = @evaluation_started = true unless @evaluation_started
      if execute
        begin
          set_state(true, @task.call, nil)
        rescue => ex
          set_state(false, nil, ex)
        end
      elsif incomplete?
        raise IllegalOperationError, 'Recursive call to #value during evaluation of the Delay'
      end
    end
    if @do_nothing_on_deref
      @value
    else
      apply_deref_options(@value)
    end
  end
end

def value!(timeout = nil)

Raises:
  • (Exception) - when `#rejected?` raises `#reason`

Returns:
  • (Object) - the current value of the object

Parameters:
  • timeout (Numeric) -- the maximum number of seconds to wait
def value!(timeout = nil)
  if @executor
    super
  else
    result = value
    raise @reason if @reason
    result
  end
end

def wait(timeout = nil)

Returns:
  • (Object) - self

Parameters:
  • timeout (Integer) -- (nil) the maximum number of seconds to wait for
def wait(timeout = nil)
  if @executor
    execute_task_once
    super(timeout)
  else
    value
  end
  self
end