Class: Concurrent::Promises::Future — Concurrent Ruby

# Class: Concurrent::Promises::Future

Inherits:
  AbstractEventFuture
  - Object
  - Synchronization::Object
  - AbstractEventFuture
  - Concurrent::Promises::Future
  show all

Includes:
  ActorIntegration, FlatShortcuts, NewChannelIntegration

Defined in:
  lib/concurrent/promises.rb,
  lib-edge/concurrent/edge/promises.rb,
  lib-edge/concurrent/edge/promises.rb,
  lib-edge/concurrent/edge/old_channel_integration.rb

## Overview

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

## Direct Known Subclasses

ResolvableFuture

## Defined Under Namespace

Modules: ActorIntegration, FlatShortcuts, NewChannelIntegration

## Instance Method Summary collapse

- #any(event_or_future) ⇒ Future (also: #|)

  Creates a new event which will be resolved when the first of receiver, `event_or_future` resolves.

- #delay ⇒ Future

  Creates new future dependent on receiver which will not evaluate until touched, see AbstractEventFuture#touch.

- #exception(*args) ⇒ Exception

  Allows rejected Future to be risen with `raise` method.

- #flat_event ⇒ Event

  Creates new event which will be resolved when the returned event by receiver is.

- #flat_future(level = 1) ⇒ Future (also: #flat)

  Creates new future which will have result of the future returned by receiver.

- #fulfilled? ⇒ Boolean

  Is it in fulfilled state?.

- #on_fulfillment(*args, &callback) ⇒ self

  Shortcut of #on_fulfillment_using with default `:io` executor supplied.

- #on_fulfillment!(*args) {|value, *args| ... } ⇒ self

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

- #on_fulfillment_using(executor, *args) {|value, *args| ... } ⇒ self

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

- #on_rejection(*args, &callback) ⇒ self

  Shortcut of #on_rejection_using with default `:io` executor supplied.

- #on_rejection!(*args) {|reason, *args| ... } ⇒ self

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

- #on_rejection_using(executor, *args) {|reason, *args| ... } ⇒ self

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

- #reason(timeout = nil, timeout_value = nil) ⇒ Object, timeout_value

  Returns reason of future's rejection.

- #rejected? ⇒ Boolean

  Is it in rejected state?.

- #rescue(*args, &task) ⇒ Future

  Shortcut of #rescue_on with default `:io` executor supplied.

- #rescue_on(executor, *args) {|reason, *args| ... } ⇒ Future

  Chains the task to be executed asynchronously on executor after it rejects.

- #result(timeout = nil) ⇒ Array(Boolean, Object, Object), nil

  Returns triplet fulfilled?, value, reason.

- #run(run_test = method(:run_test)) ⇒ Future

  Allows to use futures as green threads.

- #schedule(intended_time) ⇒ Future

  Creates new event dependent on receiver scheduled to execute on/in intended_time.

- #then(*args, &task) ⇒ Future

  Shortcut of #then_on with default `:io` executor supplied.

- #then_on(executor, *args) {|value, *args| ... } ⇒ Future

  Chains the task to be executed asynchronously on executor after it fulfills.

- #to_event ⇒ Event

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

- #to_future ⇒ Future

  Returns self, since this is a future.

- #to_s ⇒ String (also: #inspect)

  Short string representation.

- #value(timeout = nil, timeout_value = nil) ⇒ Object, nil, timeout_value

  Return value of the future.

- #value!(timeout = nil, timeout_value = nil) ⇒ Object, nil, timeout_value

  Return value of the future.

- #wait!(timeout = nil) ⇒ self, true, false

  Wait (block the Thread) until receiver is AbstractEventFuture#resolved?.

- #with_default_executor(executor) ⇒ Future

  Crates new object with same class with the executor set as its new default executor.

- #zip(other) ⇒ Future (also: #&)

  Creates a new event or a future which will be resolved when receiver and other are.

- #then_ask(actor) ⇒ Future included from ActorIntegration

  Asks the actor with its value.

- #then_channel_push(channel) ⇒ Future included from NewChannelIntegration

  A future which is fulfilled after the message is pushed to the channel.

- #then_flat_event(*args, &block) ⇒ Event included from FlatShortcuts
- #then_flat_event_on(executor, *args, &block) ⇒ Event included from FlatShortcuts
- #then_flat_future(*args, &block) ⇒ Future (also: #then_flat) included from FlatShortcuts
- #then_flat_future_on(executor, *args, &block) ⇒ Future (also: #then_flat_on) included from FlatShortcuts

## Instance Method Details

### #any(event_or_future) ⇒ `Future` Also known as: |

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.

Returns:

- (`Future`)

    1074
    1075
    1076
    # File 'lib/concurrent/promises.rb', line 1074

    def any(event_or_future)
      AnyResolvedFuturePromise.new_blocked_by2(self, event_or_future, @DefaultExecutor).future
    end

### #delay ⇒ `Future`

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

Returns:

- (`Future`)

    1084
    1085
    1086
    1087
    # File 'lib/concurrent/promises.rb', line 1084

    def delay
      event = DelayPromise.new(@DefaultExecutor).event
      ZipFutureEventPromise.new_blocked_by2(self, event, @DefaultExecutor).future
    end

### #exception(*args) ⇒ `Exception`

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

Examples:

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

Returns:

- (`Exception`)

Raises:

- (`Concurrent::Error`) —

  when raising not rejected future

    1002
    1003
    1004
    1005
    1006
    1007
    1008
    1009
    1010
    1011
    1012
    1013
    1014
    1015
    1016
    1017
    1018
    1019
    # File 'lib/concurrent/promises.rb', line 1002

    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_event ⇒ `Event`

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.

Returns:

- (`Event`)

    1119
    1120
    1121
    # File 'lib/concurrent/promises.rb', line 1119

    def flat_event
      FlatEventPromise.new_blocked_by1(self, @DefaultExecutor).event
    end

### #flat_future(level = 1) ⇒ `Future` Also known as: flat

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

Parameters:

- level (`Integer`) (defaults to: `1`) —

  how many levels of futures should flatten

Returns:

- (`Future`)

    1109
    1110
    1111
    # File 'lib/concurrent/promises.rb', line 1109

    def flat_future(level = 1)
      FlatFuturePromise.new_blocked_by1(self, level, @DefaultExecutor).future
    end

### #fulfilled? ⇒ `Boolean`

Is it in fulfilled state?

Returns:

- (`Boolean`)

    910
    911
    912
    913
    # File 'lib/concurrent/promises.rb', line 910

    def fulfilled?
      state = internal_state
      state.resolved? && state.fulfilled?
    end

### #on_fulfillment(*args, &callback) ⇒ `self`

Shortcut of #on_fulfillment_using with default `:io` executor supplied.

Returns:

- (`self`)

See Also:

- #on_fulfillment_using

    1125
    1126
    1127
    # File 'lib/concurrent/promises.rb', line 1125

    def on_fulfillment(*args, &callback)
      on_fulfillment_using @DefaultExecutor, *args, &callback
    end

### #on_fulfillment!(*args) {|value, *args| ... } ⇒ `self`

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

Parameters:

- args (`Object`) —

  arguments which are passed to the task when it's executed. (It might be prepended with other arguments, see the @yeild section).

Yields:

- (`value`, `*args`) —

  to the callback.

Yield Returns:

- is forgotten.

Returns:

- (`self`)

    1136
    1137
    1138
    # File 'lib/concurrent/promises.rb', line 1136

    def on_fulfillment!(*args, &callback)
      add_callback :callback_on_fulfillment, args, callback
    end

### #on_fulfillment_using(executor, *args) {|value, *args| ... } ⇒ `self`

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

Parameters:

- executor (`Executor`, `:io`, `:fast`) —

  Instance of an executor or a name of the global executor. The task is executed on it, default executor remains unchanged.

- args (`Object`) —

  arguments which are passed to the task when it's executed. (It might be prepended with other arguments, see the @yeild section).

Yields:

- (`value`, `*args`) —

  to the callback.

Yield Returns:

- is forgotten.

Returns:

- (`self`)

    1148
    1149
    1150
    # File 'lib/concurrent/promises.rb', line 1148

    def on_fulfillment_using(executor, *args, &callback)
      add_callback :async_callback_on_fulfillment, executor, args, callback
    end

### #on_rejection(*args, &callback) ⇒ `self`

Shortcut of #on_rejection_using with default `:io` executor supplied.

Returns:

- (`self`)

See Also:

- #on_rejection_using

    1154
    1155
    1156
    # File 'lib/concurrent/promises.rb', line 1154

    def on_rejection(*args, &callback)
      on_rejection_using @DefaultExecutor, *args, &callback
    end

### #on_rejection!(*args) {|reason, *args| ... } ⇒ `self`

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

Parameters:

- args (`Object`) —

  arguments which are passed to the task when it's executed. (It might be prepended with other arguments, see the @yeild section).

Yields:

- (`reason`, `*args`) —

  to the callback.

Yield Returns:

- is forgotten.

Returns:

- (`self`)

    1165
    1166
    1167
    # File 'lib/concurrent/promises.rb', line 1165

    def on_rejection!(*args, &callback)
      add_callback :callback_on_rejection, args, callback
    end

### #on_rejection_using(executor, *args) {|reason, *args| ... } ⇒ `self`

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

Parameters:

- executor (`Executor`, `:io`, `:fast`) —

  Instance of an executor or a name of the global executor. The task is executed on it, default executor remains unchanged.

- args (`Object`) —

  arguments which are passed to the task when it's executed. (It might be prepended with other arguments, see the @yeild section).

Yields:

- (`reason`, `*args`) —

  to the callback.

Yield Returns:

- is forgotten.

Returns:

- (`self`)

    1177
    1178
    1179
    # File 'lib/concurrent/promises.rb', line 1177

    def on_rejection_using(executor, *args, &callback)
      add_callback :async_callback_on_rejection, executor, args, callback
    end

### #reason(timeout = nil, timeout_value = nil) ⇒ `Object`, `timeout_value`

Note:

This function potentially blocks current thread until the Future is resolved. Be careful it can deadlock. Try to chain instead.

Note:

Make sure returned `nil` is not confused with timeout, no value when rejected, no reason when fulfilled, etc. Use more exact methods if needed, like AbstractEventFuture#wait, #value!, #result, etc.

Returns reason of future's rejection. Calls AbstractEventFuture#touch.

Parameters:

- timeout (`Numeric`) (defaults to: `nil`) —

  the maximum time in second to wait.

- timeout_value (`Object`) (defaults to: `nil`) —

  a value returned by the method when it times out

Returns:

- (`Object`, `timeout_value`) —

  the reason, or timeout_value on timeout, or nil on fulfillment.

    955
    956
    957
    958
    959
    960
    961
    # File 'lib/concurrent/promises.rb', line 955

    def reason(timeout = nil, timeout_value = nil)
      if wait_until_resolved timeout
        internal_state.reason
      else
        timeout_value
      end
    end

### #rejected? ⇒ `Boolean`

Is it in rejected state?

Returns:

- (`Boolean`)

    917
    918
    919
    920
    # File 'lib/concurrent/promises.rb', line 917

    def rejected?
      state = internal_state
      state.resolved? && !state.fulfilled?
    end

### #rescue(*args, &task) ⇒ `Future`

Shortcut of #rescue_on with default `:io` executor supplied.

Returns:

- (`Future`)

See Also:

- #rescue_on

    1041
    1042
    1043
    # File 'lib/concurrent/promises.rb', line 1041

    def rescue(*args, &task)
      rescue_on @DefaultExecutor, *args, &task
    end

### #rescue_on(executor, *args) {|reason, *args| ... } ⇒ `Future`

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.

Parameters:

- executor (`Executor`, `:io`, `:fast`) —

  Instance of an executor or a name of the global executor. The task is executed on it, default executor remains unchanged.

- args (`Object`) —

  arguments which are passed to the task when it's executed. (It might be prepended with other arguments, see the @yeild section).

Yields:

- (`reason`, `*args`) —

  to the task.

Yield Returns:

- will become result of the returned Future. Its returned value becomes #value fulfilling it, raised exception becomes #reason rejecting it.

Returns:

- (`Future`)

    1053
    1054
    1055
    # File 'lib/concurrent/promises.rb', line 1053

    def rescue_on(executor, *args, &task)
      RescuePromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future
    end

### #result(timeout = nil) ⇒ `Array(Boolean, Object, Object)`, `nil`

Note:

This function potentially blocks current thread until the Future is resolved. Be careful it can deadlock. Try to chain instead.

Returns triplet fulfilled?, value, reason. Calls AbstractEventFuture#touch.

Parameters:

- timeout (`Numeric`) (defaults to: `nil`) —

  the maximum time in second to wait.

Returns:

- (`Array(Boolean, Object, Object)`, `nil`) —

  triplet of fulfilled?, value, reason, or nil on timeout.

    970
    971
    972
    # File 'lib/concurrent/promises.rb', line 970

    def result(timeout = nil)
      internal_state.result if wait_until_resolved timeout
    end

### #run(run_test = method(:run_test)) ⇒ `Future`

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.

Examples:

    body = lambda do |v|
      v += 1
      v < 5 ? Promises.future(v, &body) : v
    end
    Promises.future(0, &body).run.value! # => 5

Parameters:

- run_test (`#call(value)`) (defaults to: `method(: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.

Returns:

- (`Future`)

    1199
    1200
    1201
    # File 'lib/concurrent/promises.rb', line 1199

    def run(run_test = method(:run_test))
      RunFuturePromise.new_blocked_by1(self, @DefaultExecutor, run_test).future
    end

### #schedule(intended_time) ⇒ `Future`

Creates new event dependent on receiver scheduled to execute on/in intended_time. In time is interpreted from the moment the receiver is resolved, therefore it inserts delay into the chain.

Parameters:

- intended_time (`Numeric`, `Time`) —

  `Numeric` means to run in `intended_time` seconds. `Time` means to run on `intended_time`.

Returns:

- (`Future`)

    1091
    1092
    1093
    1094
    1095
    1096
    # File 'lib/concurrent/promises.rb', line 1091

    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) ⇒ `Future`

Shortcut of #then_on with default `:io` executor supplied.

Returns:

- (`Future`)

See Also:

- #then_on

    1023
    1024
    1025
    # File 'lib/concurrent/promises.rb', line 1023

    def then(*args, &task)
      then_on @DefaultExecutor, *args, &task
    end

### #then_on(executor, *args) {|value, *args| ... } ⇒ `Future`

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.

Parameters:

- executor (`Executor`, `:io`, `:fast`) —

  Instance of an executor or a name of the global executor. The task is executed on it, default executor remains unchanged.

- args (`Object`) —

  arguments which are passed to the task when it's executed. (It might be prepended with other arguments, see the @yeild section).

Yields:

- (`value`, `*args`) —

  to the task.

Yield Returns:

- will become result of the returned Future. Its returned value becomes #value fulfilling it, raised exception becomes #reason rejecting it.

Returns:

- (`Future`)

    1035
    1036
    1037
    # File 'lib/concurrent/promises.rb', line 1035

    def then_on(executor, *args, &task)
      ThenPromise.new_blocked_by1(self, @DefaultExecutor, executor, args, &task).future
    end

### #to_event ⇒ `Event`

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

Returns:

- (`Event`)

    1211
    1212
    1213
    1214
    1215
    # File 'lib/concurrent/promises.rb', line 1211

    def to_event
      event = Promises.resolvable_event
    ensure
      chain_resolvable(event)
    end

### #to_future ⇒ `Future`

Returns self, since this is a future

Returns:

- (`Future`)

    1219
    1220
    1221
    # File 'lib/concurrent/promises.rb', line 1219

    def to_future
      self
    end

### #to_s ⇒ `String` Also known as: inspect

Returns Short string representation.

Returns:

- (`String`) —

  Short string representation.

    1224
    1225
    1226
    1227
    1228
    1229
    1230
    # File 'lib/concurrent/promises.rb', line 1224

    def to_s
      if resolved?
        format '%s with %s>', super[0..-2], (fulfilled? ? value : reason).inspect
      else
        super
      end
    end

### #value(timeout = nil, timeout_value = nil) ⇒ `Object`, `nil`, `timeout_value`

Note:

This function potentially blocks current thread until the Future is resolved. Be careful it can deadlock. Try to chain instead.

Note:

Make sure returned `nil` is not confused with timeout, no value when rejected, no reason when fulfilled, etc. Use more exact methods if needed, like AbstractEventFuture#wait, #value!, #result, etc.

Return value of the future. Calls AbstractEventFuture#touch.

Parameters:

- timeout (`Numeric`) (defaults to: `nil`) —

  the maximum time in second to wait.

- timeout_value (`Object`) (defaults to: `nil`) —

  a value returned by the method when it times out

Returns:

- (`Object`, `nil`, `timeout_value`) —

  the value of the Future when fulfilled, timeout_value on timeout, nil on rejection.

    939
    940
    941
    942
    943
    944
    945
    # File 'lib/concurrent/promises.rb', line 939

    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) ⇒ `Object`, `nil`, `timeout_value`

Note:

This function potentially blocks current thread until the Future is resolved. Be careful it can deadlock. Try to chain instead.

Note:

Make sure returned `nil` is not confused with timeout, no value when rejected, no reason when fulfilled, etc. Use more exact methods if needed, like AbstractEventFuture#wait, #value!, #result, etc.

Return value of the future. Calls AbstractEventFuture#touch.

Parameters:

- timeout (`Numeric`) (defaults to: `nil`) —

  the maximum time in second to wait.

- timeout_value (`Object`) (defaults to: `nil`) —

  a value returned by the method when it times out

Returns:

- (`Object`, `nil`, `timeout_value`) —

  the value of the Future when fulfilled, or nil on rejection, or timeout_value on timeout.

Raises:

- (`Exception`) —

  #reason on rejection

    986
    987
    988
    989
    990
    991
    992
    # File 'lib/concurrent/promises.rb', line 986

    def value!(timeout = nil, timeout_value = nil)
      if wait_until_resolved! timeout
        internal_state.value
      else
        timeout_value
      end
    end

### #wait!(timeout = nil) ⇒ `self`, `true`, `false`

Note:

This function potentially blocks current thread until the Future is resolved. Be careful it can deadlock. Try to chain instead.

Wait (block the Thread) until receiver is AbstractEventFuture#resolved?. Calls AbstractEventFuture#touch.

Parameters:

- timeout (`Numeric`) (defaults to: `nil`) —

  the maximum time in second to wait.

Returns:

- (`self`, `true`, `false`) —

  self implies timeout was not used, true implies timeout was used and it was resolved, false implies it was not resolved within timeout.

Raises:

- (`Exception`) —

  #reason on rejection

    976
    977
    978
    979
    # File 'lib/concurrent/promises.rb', line 976

    def wait!(timeout = nil)
      result = wait_until_resolved!(timeout)
      timeout ? result : self
    end

### #with_default_executor(executor) ⇒ `Future`

Crates new object with same class with the executor set as its new default executor. Any futures depending on it will use the new default executor.

Returns:

- (`Future`)

    1100
    1101
    1102
    # File 'lib/concurrent/promises.rb', line 1100

    def with_default_executor(executor)
      FutureWrapperPromise.new_blocked_by1(self, executor).future
    end

### #zip(other) ⇒ `Future` Also known as: &

Creates a new event or a future which will be resolved when receiver and other are. Returns an event if receiver and other are events, otherwise returns a future. If just one of the parties is Future then the result of the returned future is equal to the result of the supplied future. If both are futures then the result is as described in Concurrent::Promises::FactoryMethods#zip_futures_on.

Returns:

- (`Future`)

    1059
    1060
    1061
    1062
    1063
    1064
    1065
    # File 'lib/concurrent/promises.rb', line 1059

    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

### #then_ask(actor) ⇒ `Future` Originally defined in module ActorIntegration

Asks the actor with its value.

Returns:

- (`Future`) —

  new future with the response form the actor

### #then_channel_push(channel) ⇒ `Future` Originally defined in module NewChannelIntegration

Returns a future which is fulfilled after the message is pushed to the channel. May take a moment if the channel is full.

Parameters:

- channel (`Channel`) —

  to push to.

Returns:

- (`Future`) —

  a future which is fulfilled after the message is pushed to the channel. May take a moment if the channel is full.

### #then_flat_event(*args, &block) ⇒ `Event` Originally defined in module FlatShortcuts

Returns:

- (`Event`)

### #then_flat_event_on(executor, *args, &block) ⇒ `Event` Originally defined in module FlatShortcuts

Returns:

- (`Event`)

### #then_flat_future(*args, &block) ⇒ `Future` Also known as: then_flat Originally defined in module FlatShortcuts

Returns:

- (`Future`)

### #then_flat_future_on(executor, *args, &block) ⇒ `Future` Also known as: then_flat_on Originally defined in module FlatShortcuts

Returns:

- (`Future`)