class Concurrent::Promises::Future

Represents a value which will become available in future. May reject with a reason instead, e.g. when the tasks raises an exception.

Public Instance Methods

&(other)
Alias for: zip
any(event_or_future) click to toggle source

Creates a new event which will be resolved when the first of receiver, ‘event_or_future` resolves. Returning future will have value nil if event_or_future is event and resolves first.

@return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1075
def any(event_or_future)
  AnyResolvedFuturePromise.new_blocked_by2(self, event_or_future, @DefaultExecutor).future
end
Also aliased as: |
apply(args, block) click to toggle source

@!visibility private

# File lib/concurrent-ruby/concurrent/promises.rb, line 1205
def apply(args, block)
  internal_state.apply args, block
end
delay() click to toggle source

Creates new future dependent on receiver which will not evaluate until touched, see {#touch}. In other words, it inserts delay into the chain of Futures making rest of it lazy evaluated.

@return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1085
def delay
  event = DelayPromise.new(@DefaultExecutor).event
  ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future
end
exception(*args) click to toggle source

Allows rejected Future to be risen with ‘raise` method. If the reason is not an exception `Runtime.new(reason)` is returned.

@example

raise Promises.rejected_future(StandardError.new("boom"))
raise Promises.rejected_future("or just boom")

@raise [Concurrent::Error] when raising not rejected future @return [Exception]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1003
def exception(*args)
  raise Concurrent::Error, 'it is not rejected' unless rejected?
  raise ArgumentError unless args.size <= 1
  reason = Array(internal_state.reason).flatten.compact
  if reason.size > 1
    ex = Concurrent::MultipleErrors.new reason
    ex.set_backtrace(caller)
    ex
  else
    ex = if reason[0].respond_to? :exception
           reason[0].exception(*args)
         else
           RuntimeError.new(reason[0]).exception(*args)
         end
    ex.set_backtrace Array(ex.backtrace) + caller
    ex
  end
end
flat(level = 1)
Alias for: flat_future
flat_event() click to toggle source

Creates new event which will be resolved when the returned event by receiver is. Be careful if the receiver rejects it will just resolve since Event does not hold reason.

@return [Event]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1120
def flat_event
  FlatEventPromise.new_blocked_by1(self, @DefaultExecutor).event
end
flat_future(level = 1) click to toggle source

Creates new future which will have result of the future returned by receiver. If receiver rejects it will have its rejection.

@param [Integer] level how many levels of futures should flatten @return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1110
def flat_future(level = 1)
  FlatFuturePromise.new_blocked_by1(self, level, @DefaultExecutor).future
end
Also aliased as: flat
fulfilled?() click to toggle source

Is it in fulfilled state? @return [Boolean]

# File lib/concurrent-ruby/concurrent/promises.rb, line 911
def fulfilled?
  state = internal_state
  state.resolved? && state.fulfilled?
end
inspect()
Alias for: to_s
on_fulfillment(*args, &callback) click to toggle source

@!macro promises.shortcut.using @return [self]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1126
def on_fulfillment(*args, &callback)
  on_fulfillment_using @DefaultExecutor, *args, &callback
end
on_fulfillment!(*args, &callback) click to toggle source

Stores the callback to be executed synchronously on resolving thread after it is fulfilled. Does nothing on rejection.

@!macro promises.param.args @!macro promise.param.callback @return [self] @yield [value, *args] to the callback.

# File lib/concurrent-ruby/concurrent/promises.rb, line 1137
def on_fulfillment!(*args, &callback)
  add_callback :callback_on_fulfillment, args, callback
end
on_fulfillment_using(executor, *args, &callback) click to toggle source

Stores the callback to be executed asynchronously on executor after it is fulfilled. Does nothing on rejection.

@!macro promises.param.executor @!macro promises.param.args @!macro promise.param.callback @return [self] @yield [value, *args] to the callback.

# File lib/concurrent-ruby/concurrent/promises.rb, line 1149
def on_fulfillment_using(executor, *args, &callback)
  add_callback :async_callback_on_fulfillment, executor, args, callback
end
on_rejection(*args, &callback) click to toggle source

@!macro promises.shortcut.using @return [self]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1155
def on_rejection(*args, &callback)
  on_rejection_using @DefaultExecutor, *args, &callback
end
on_rejection!(*args, &callback) click to toggle source

Stores the callback to be executed synchronously on resolving thread after it is rejected. Does nothing on fulfillment.

@!macro promises.param.args @!macro promise.param.callback @return [self] @yield [reason, *args] to the callback.

# File lib/concurrent-ruby/concurrent/promises.rb, line 1166
def on_rejection!(*args, &callback)
  add_callback :callback_on_rejection, args, callback
end
on_rejection_using(executor, *args, &callback) click to toggle source

Stores the callback to be executed asynchronously on executor after it is rejected. Does nothing on fulfillment.

@!macro promises.param.executor @!macro promises.param.args @!macro promise.param.callback @return [self] @yield [reason, *args] to the callback.

# File lib/concurrent-ruby/concurrent/promises.rb, line 1178
def on_rejection_using(executor, *args, &callback)
  add_callback :async_callback_on_rejection, executor, args, callback
end
reason(timeout = nil, timeout_value = nil) click to toggle source

Returns reason of future’s rejection. @!macro promises.touches

@!macro promises.warn.blocks @!macro promises.warn.nil @!macro promises.param.timeout @!macro promises.param.timeout_value @return [Object, timeout_value] the reason, or timeout_value on timeout, or nil on fulfillment.

# File lib/concurrent-ruby/concurrent/promises.rb, line 956
def reason(timeout = nil, timeout_value = nil)
  if wait_until_resolved timeout
    internal_state.reason
  else
    timeout_value
  end
end
rejected?() click to toggle source

Is it in rejected state? @return [Boolean]

# File lib/concurrent-ruby/concurrent/promises.rb, line 918
def rejected?
  state = internal_state
  state.resolved? && !state.fulfilled?
end
rescue(*args, &task) click to toggle source

@!macro promises.shortcut.on @return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1042
def rescue(*args, &task)
  rescue_on @DefaultExecutor, *args, &task
end
rescue_on(executor, *args, &task) click to toggle source

Chains the task to be executed asynchronously on executor after it rejects. Does not run the task if it fulfills. It will resolve though, triggering any dependent futures.

@!macro promises.param.executor @!macro promises.param.args @!macro promise.param.task-future @return [Future] @yield [reason, *args] to the task.

# File lib/concurrent-ruby/concurrent/promises.rb, line 1054
def rescue_on(executor, *args, &task)
  RescuePromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future
end
result(timeout = nil) click to toggle source

Returns triplet fulfilled?, value, reason. @!macro promises.touches

@!macro promises.warn.blocks @!macro promises.param.timeout @return [Array(Boolean, Object, Object), nil] triplet of fulfilled?, value, reason, or nil

on timeout.
# File lib/concurrent-ruby/concurrent/promises.rb, line 971
def result(timeout = nil)
  internal_state.result if wait_until_resolved timeout
end
run(run_test = method(:run_test)) click to toggle source

Allows to use futures as green threads. The receiver has to evaluate to a future which represents what should be done next. It basically flattens indefinitely until non Future values is returned which becomes result of the returned future. Any encountered exception will become reason of the returned future.

@return [Future] @param [#call(value)] run_test

an object which when called returns either Future to keep running with
or nil, then the run completes with the value.
The run_test can be used to extract the Future from deeper structure,
or to distinguish Future which is a resulting value from a future
which is suppose to continue running.

@example

body = lambda do |v|
  v += 1
  v < 5 ? Promises.future(v, &body) : v
end
Promises.future(0, &body).run.value! # => 5
# File lib/concurrent-ruby/concurrent/promises.rb, line 1200
def run(run_test = method(:run_test))
  RunFuturePromise.new_blocked_by1(self, @DefaultExecutor, run_test).future
end
schedule(intended_time) click to toggle source

@!macro promise.method.schedule @return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1092
def schedule(intended_time)
  chain do
    event = ScheduledPromise.new(@DefaultExecutor, intended_time).event
    ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future
  end.flat
end
then(*args, &task) click to toggle source

@!macro promises.shortcut.on @return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1024
def then(*args, &task)
  then_on @DefaultExecutor, *args, &task
end
then_on(executor, *args, &task) click to toggle source

Chains the task to be executed asynchronously on executor after it fulfills. Does not run the task if it rejects. It will resolve though, triggering any dependent futures.

@!macro promises.param.executor @!macro promises.param.args @!macro promise.param.task-future @return [Future] @yield [value, *args] to the task.

# File lib/concurrent-ruby/concurrent/promises.rb, line 1036
def then_on(executor, *args, &task)
  ThenPromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future
end
to_event() click to toggle source

Converts future to event which is resolved when future is resolved by fulfillment or rejection.

@return [Event]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1212
def to_event
  event = Promises.resolvable_event
ensure
  chain_resolvable(event)
end
to_future() click to toggle source

Returns self, since this is a future @return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1220
def to_future
  self
end
to_s() click to toggle source

@return [String] Short string representation.

# File lib/concurrent-ruby/concurrent/promises.rb, line 1225
def to_s
  if resolved?
    format '%s with %s>', super[0..-2], (fulfilled? ? value : reason).inspect
  else
    super
  end
end
Also aliased as: inspect
value(timeout = nil, timeout_value = nil) click to toggle source

@!macro promises.method.value

Return value of the future.
@!macro promises.touches

@!macro promises.warn.blocks
@!macro promises.warn.nil
@!macro promises.param.timeout
@!macro promises.param.timeout_value
  @param [Object] timeout_value a value returned by the method when it times out

@return [Object, nil, timeout_value] the value of the Future when fulfilled,

timeout_value on timeout,
nil on rejection.
# File lib/concurrent-ruby/concurrent/promises.rb, line 940
def value(timeout = nil, timeout_value = nil)
  if wait_until_resolved timeout
    internal_state.value
  else
    timeout_value
  end
end
value!(timeout = nil, timeout_value = nil) click to toggle source

@!macro promises.method.value @return [Object, nil, timeout_value] the value of the Future when fulfilled,

or nil on rejection,
or timeout_value on timeout.

@raise [Exception] {#reason} on rejection

# File lib/concurrent-ruby/concurrent/promises.rb, line 987
def value!(timeout = nil, timeout_value = nil)
  if wait_until_resolved! timeout
    internal_state.value
  else
    timeout_value
  end
end
wait!(timeout = nil) click to toggle source

@!macro promises.method.wait @raise [Exception] {#reason} on rejection

# File lib/concurrent-ruby/concurrent/promises.rb, line 977
def wait!(timeout = nil)
  result = wait_until_resolved!(timeout)
  timeout ? result : self
end
with_default_executor(executor) click to toggle source

@!macro promises.method.with_default_executor @return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1101
def with_default_executor(executor)
  FutureWrapperPromise.new_blocked_by1(self, executor).future
end
zip(other) click to toggle source

@!macro promises.method.zip @return [Future]

# File lib/concurrent-ruby/concurrent/promises.rb, line 1060
def zip(other)
  if other.is_a?(Future)
    ZipFuturesPromise.new_blocked_by2(self, other, @DefaultExecutor).future
  else
    ZipFutureEventPromise.new_blocked_by2(self, other, @DefaultExecutor).future
  end
end
Also aliased as: &
|(event_or_future)
Alias for: any

Private Instance Methods

async_callback_on_fulfillment(state, executor, args, callback) click to toggle source
# File lib/concurrent-ruby/concurrent/promises.rb, line 1262
def async_callback_on_fulfillment(state, executor, args, callback)
  with_async(executor, state, args, callback) do |st, ar, cb|
    callback_on_fulfillment st, ar, cb
  end
end
async_callback_on_rejection(state, executor, args, callback) click to toggle source
# File lib/concurrent-ruby/concurrent/promises.rb, line 1268
def async_callback_on_rejection(state, executor, args, callback)
  with_async(executor, state, args, callback) do |st, ar, cb|
    callback_on_rejection st, ar, cb
  end
end
callback_on_fulfillment(state, args, callback) click to toggle source
# File lib/concurrent-ruby/concurrent/promises.rb, line 1274
def callback_on_fulfillment(state, args, callback)
  state.apply args, callback if state.fulfilled?
end
callback_on_rejection(state, args, callback) click to toggle source
# File lib/concurrent-ruby/concurrent/promises.rb, line 1278
def callback_on_rejection(state, args, callback)
  state.apply args, callback unless state.fulfilled?
end
callback_on_resolution(state, args, callback) click to toggle source
# File lib/concurrent-ruby/concurrent/promises.rb, line 1282
def callback_on_resolution(state, args, callback)
  callback.call(*state.result, *args)
end
rejected_resolution(raise_on_reassign, state) click to toggle source
# File lib/concurrent-ruby/concurrent/promises.rb, line 1241
def rejected_resolution(raise_on_reassign, state)
  if raise_on_reassign
    if internal_state == RESERVED
      raise Concurrent::MultipleAssignmentError.new(
          "Future can be resolved only once. It is already reserved.")
    else
      raise Concurrent::MultipleAssignmentError.new(
          "Future can be resolved only once. It's #{result}, trying to set #{state.result}.",
          current_result: result,
          new_result:     state.result)
    end
  end
  return false
end
run_test(v) click to toggle source
# File lib/concurrent-ruby/concurrent/promises.rb, line 1237
def run_test(v)
  v if v.is_a?(Future)
end
wait_until_resolved!(timeout = nil) click to toggle source
# File lib/concurrent-ruby/concurrent/promises.rb, line 1256
def wait_until_resolved!(timeout = nil)
  result = wait_until_resolved(timeout)
  raise self if rejected?
  result
end