class Px::Service::Client::Future

Public Class Methods

new() { || ... } click to toggle source

Create a new future. If a block is given, it is executed and the future is automatically completed with the block's return value

# File lib/px/service/client/future.rb, line 12
def initialize
  @completed = false
  @pending_calls = []

  if block_given?
    Fiber.new do
      value = begin
        yield
      rescue Exception => ex
        ex
      end
      complete(value)
    end.resume
  end
end

Public Instance Methods

complete(value) click to toggle source
# File lib/px/service/client/future.rb, line 28
def complete(value)
  raise AlreadyCompletedError.new if @completed

  @value = value
  @completed = true
  @pending_calls.each do |pending_call|
    if value.kind_of?(Exception)
      pending_call[:fiber].resume(value)
    else
      result = nil
      begin
        if pending_call[:method]
          result = value.send(pending_call[:method], *pending_call[:args])
        else
          result = value
        end
      rescue Exception => ex
        result = ex
      end
      pending_call[:fiber].resume(result)
    end
  end
end
completed?() click to toggle source
# File lib/px/service/client/future.rb, line 76
def completed?
  @completed
end
method_missing(method, *args) click to toggle source
Calls superclass method
# File lib/px/service/client/future.rb, line 80
def method_missing(method, *args)
  super unless respond_to_missing?(method)
  value!.send(method, *args)
end
respond_to_missing?(method, include_private = false) click to toggle source
# File lib/px/service/client/future.rb, line 85
def respond_to_missing?(method, include_private = false)
  # NoMethodError is handled by method_missing here, so that exceptions
  # are raised properly even though they don't respond_to the same things
  # as the future values themselves
  true
end
value() click to toggle source
# File lib/px/service/client/future.rb, line 52
def value
  if @completed
    @value
  else
    wait_for_value(nil)
  end
end
value!() click to toggle source
# File lib/px/service/client/future.rb, line 60
def value!
  if @completed
    result = @value
  else
    result = wait_for_value(nil)
  end

  if result.kind_of?(Exception)
    # Set the backtrack properly to reflect where this method is called
    result.set_backtrace(caller)
    raise result
  end

  result
end

Private Instance Methods

wait_for_value(method, *args) click to toggle source
# File lib/px/service/client/future.rb, line 94
def wait_for_value(method, *args)
  # TODO: check for root fiber
  @pending_calls << { fiber: Fiber.current, method: method, args: args }
  Fiber.yield
end