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/promises.rb, line 1023
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/promises.rb, line 1147
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/promises.rb, line 1033
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. @example

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

@raise [StandardError] when raising not rejected future @return [Exception]

# File lib/concurrent/promises.rb, line 956
def exception(*args)
  raise Concurrent::Error, 'it is not rejected' unless rejected?
  reason = Array(internal_state.reason).flatten.compact
  if reason.size > 1
    ex = Concurrent::MultipleErrors.new reason
    ex.set_backtrace(caller)
    ex
  else
    ex = reason[0].clone.exception(*args)
    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/promises.rb, line 1068
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/promises.rb, line 1058
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/promises.rb, line 886
def fulfilled?
  state = internal_state
  state.resolved? && state.fulfilled?
end
on_fulfillment(*args, &callback) click to toggle source

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

# File lib/concurrent/promises.rb, line 1074
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/promises.rb, line 1085
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/promises.rb, line 1097
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/promises.rb, line 1103
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/promises.rb, line 1114
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/promises.rb, line 1126
def on_rejection_using(executor, *args, &callback)
  add_callback :async_callback_on_rejection, executor, args, callback
end
reason(timeout = 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 @return [Exception, nil] nil on timeout or fulfillment.

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

Is it in rejected state? @return [Boolean]

# File lib/concurrent/promises.rb, line 893
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/promises.rb, line 990
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/promises.rb, line 1002
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, Exception), nil] triplet of fulfilled?, value, reason, or nil

on timeout.
# File lib/concurrent/promises.rb, line 933
def result(timeout = nil)
  internal_state.result if wait_until_resolved timeout
end
run() 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] @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/promises.rb, line 1142
def run
  RunFuturePromise.new_blocked_by1(self, @DefaultExecutor).future
end
schedule(intended_time) click to toggle source

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

# File lib/concurrent/promises.rb, line 1040
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/promises.rb, line 972
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/promises.rb, line 984
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/promises.rb, line 1154
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/promises.rb, line 1162
def to_future
  self
end
value(timeout = 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

@return [Object, nil] the value of the Future when fulfilled, nil on timeout or rejection.

# File lib/concurrent/promises.rb, line 911
def value(timeout = nil)
  internal_state.value if wait_until_resolved timeout
end
value!(timeout = nil) click to toggle source

@!macro promises.method.value @return [Object, nil] the value of the Future when fulfilled, nil on timeout. @raise [Exception] {#reason} on rejection

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

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

# File lib/concurrent/promises.rb, line 939
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/promises.rb, line 1049
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/promises.rb, line 1008
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/promises.rb, line 1183
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/promises.rb, line 1189
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/promises.rb, line 1195
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/promises.rb, line 1199
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/promises.rb, line 1203
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/promises.rb, line 1168
def rejected_resolution(raise_on_reassign, state)
  if raise_on_reassign
    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
  return false
end
wait_until_resolved!(timeout = nil) click to toggle source
# File lib/concurrent/promises.rb, line 1177
def wait_until_resolved!(timeout = nil)
  result = wait_until_resolved(timeout)
  raise self if rejected?
  result
end