Module: Concurrent::Promises — Concurrent Ruby

# Module: Concurrent::Promises

Extended by:
  FactoryMethods

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

## Overview

Promises is a new framework unifying former tools `Concurrent::Future`, `Concurrent::Promise`, `Concurrent::IVar`, `Concurrent::Event`, `Concurrent.dataflow`, `Delay`, and `TimerTask` of concurrent-ruby. It extensively uses the new synchronization layer to make all the methods lock-free (with the exception of obviously blocking operations like `#wait`, `#value`, etc.). As a result it lowers danger of deadlocking and offers better performance.

It provides similar tools as other promise libraries do, users coming from other languages and other promise libraries will find the same tools here (probably named differently though). The naming conventions were borrowed heavily from JS promises.

This framework, however, is not just a re-implementation of other promise library, it draws inspiration from many other promise libraries, adds new ideas, and is integrated with other abstractions like actors and channels.

Therefore it is likely that user will find a suitable solution for a problem in this framework. If the problem is simple user can pick one suitable abstraction, e.g. just promises or actors. If the problem is complex user can combine parts (promises, channels, actors) which were designed to work together well to a solution. Rather than having to combine fragilely independent tools.

This framework allows its users to:

- Process tasks asynchronously
- Chain, branch, and zip the asynchronous tasks together
  - Therefore, to create directed acyclic graph (hereafter DAG) of tasks
- Create delayed tasks (or delayed DAG of tasks)
- Create scheduled tasks (or delayed DAG of tasks)
- Deal with errors through rejections
- Reduce danger of deadlocking
- Control the concurrency level of tasks
- Simulate thread-like processing without occupying threads
  - It allows to create tens of thousands simulations on one thread pool
  - It works well on all Ruby implementations
- Use actors to maintain isolated states and to seamlessly combine it with promises
- Build parallel processing stream system with back pressure (parts, which are not keeping up, signal to the other parts of the system to slow down).

The guide is best place to start with promises.

# Main classes

The main public user-facing classes are Event and Future which share common ancestor AbstractEventFuture.

AbstractEventFuture:

> Common ancestor of Event and Future classes, many shared methods are defined here.

Event:

> Represents an event which will happen in future (will be resolved). The event is either pending or resolved. It should be always resolved. Use Future to communicate rejections and cancellation.

Future:

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

## Defined Under Namespace

Modules: FactoryMethods, Resolvable Classes: AbstractEventFuture, Channel, Event, Future, ResolvableEvent, ResolvableFuture

## Class Method Summary collapse

- .any_event(*futures_and_or_events) ⇒ Future extended from FactoryMethods

  Shortcut of FactoryMethods#any_event_on with default `:io` executor supplied.

- .any_event_on(default_executor, *futures_and_or_events) ⇒ Event extended from FactoryMethods

  Creates new event which becomes resolved after first of the futures_and_or_events resolves.

- .any_fulfilled_future(*futures_and_or_events) ⇒ Future extended from FactoryMethods

  Shortcut of FactoryMethods#any_fulfilled_future_on with default `:io` executor supplied.

- .any_fulfilled_future_on(default_executor, *futures_and_or_events) ⇒ Future extended from FactoryMethods

  Creates new future which is resolved after first of futures_and_or_events is fulfilled.

- .any_resolved_future(*futures_and_or_events) ⇒ Future (also: #any) extended from FactoryMethods

  Shortcut of FactoryMethods#any_resolved_future_on with default `:io` executor supplied.

- .any_resolved_future_on(default_executor, *futures_and_or_events) ⇒ Future extended from FactoryMethods

  Creates new future which is resolved after first futures_and_or_events is resolved.

- .default_executor ⇒ Executor, :io, :fast extended from FactoryMethods::Configuration

  The executor which is used when none is supplied to a factory method.

- .delay(*args, &task) ⇒ Future extended from FactoryMethods

  Shortcut of FactoryMethods#delay_on with default `:io` executor supplied.

- .delay_on(default_executor, *args) {|*args| ... } ⇒ Future extended from FactoryMethods

  Constructs new Future which will be resolved after block is evaluated on default executor.

- .fulfilled_future(value, default_executor = self.default_executor) ⇒ Future extended from FactoryMethods

  Creates resolved future with will be fulfilled with the given value.

- .future(*args, &task) ⇒ Future extended from FactoryMethods

  Shortcut of FactoryMethods#future_on with default `:io` executor supplied.

- .future_on(default_executor, *args) {|*args| ... } ⇒ Future extended from FactoryMethods

  Constructs new Future which will be resolved after block is evaluated on default executor.

- .make_future(argument = nil, default_executor = self.default_executor) ⇒ Event, Future extended from FactoryMethods

  General constructor.

- .rejected_future(reason, default_executor = self.default_executor) ⇒ Future extended from FactoryMethods

  Creates resolved future with will be rejected with the given reason.

- .resolvable_event ⇒ ResolvableEvent extended from FactoryMethods

  Shortcut of FactoryMethods#resolvable_event_on with default `:io` executor supplied.

- .resolvable_event_on(default_executor = self.default_executor) ⇒ ResolvableEvent extended from FactoryMethods

  Created resolvable event, user is responsible for resolving the event once by ResolvableEvent#resolve.

- .resolvable_future ⇒ ResolvableFuture extended from FactoryMethods

  Shortcut of FactoryMethods#resolvable_future_on with default `:io` executor supplied.

- .resolvable_future_on(default_executor = self.default_executor) ⇒ ResolvableFuture extended from FactoryMethods

  Creates resolvable future, user is responsible for resolving the future once by ResolvableFuture#resolve, ResolvableFuture#fulfill, or ResolvableFuture#reject.

- .resolved_event(default_executor = self.default_executor) ⇒ Event extended from FactoryMethods

  Creates resolved event.

- .resolved_future(fulfilled, value, reason, default_executor = self.default_executor) ⇒ Future extended from FactoryMethods

  Creates resolved future with will be either fulfilled with the given value or rejection with the given reason.

- .schedule(intended_time, *args, &task) ⇒ Future extended from FactoryMethods

  Shortcut of FactoryMethods#schedule_on with default `:io` executor supplied.

- .schedule_on(default_executor, intended_time, *args) {|*args| ... } ⇒ Future extended from FactoryMethods

  Constructs new Future which will be resolved after block is evaluated on default executor.

- .select_channel(*channels) ⇒ Future extended from FactoryMethods::NewChannelIntegration

  Selects a channel which is ready to be read from.

- .zip_events(*futures_and_or_events) ⇒ Event extended from FactoryMethods

  Shortcut of FactoryMethods#zip_events_on with default `:io` executor supplied.

- .zip_events_on(default_executor, *futures_and_or_events) ⇒ Event extended from FactoryMethods

  Creates new event which is resolved after all futures_and_or_events are resolved.

- .zip_futures(*futures_and_or_events) ⇒ Future (also: #zip) extended from FactoryMethods

  Shortcut of FactoryMethods#zip_futures_on with default `:io` executor supplied.

- .zip_futures_on(default_executor, *futures_and_or_events) ⇒ Future extended from FactoryMethods

  Creates new future which is resolved after all futures_and_or_events are resolved.

- .zip_futures_over(enumerable, &future_factory) ⇒ Future extended from FactoryMethods

  Shortcut of FactoryMethods#zip_futures_over_on with default `:io` executor supplied.

- .zip_futures_over_on(default_executor, enumerable) {|element| ... } ⇒ Future extended from FactoryMethods

  Creates new future which is resolved after all the futures created by future_factory from enumerable elements are resolved.

## Class Method Details

### .any_event(*futures_and_or_events) ⇒ `Future` Originally defined in module FactoryMethods

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

Returns:

- (`Future`)

See Also:

- #any_event_on

### .any_event_on(default_executor, *futures_and_or_events) ⇒ `Event` Originally defined in module FactoryMethods

Creates new event which becomes resolved after first of the futures_and_or_events resolves. If resolved it does not propagate AbstractEventFuture#touch, leaving delayed futures un-executed if they are not required any more.

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- futures_and_or_events (`AbstractEventFuture`)

Returns:

- (`Event`)

### .any_fulfilled_future(*futures_and_or_events) ⇒ `Future` Originally defined in module FactoryMethods

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

Returns:

- (`Future`)

See Also:

- #any_fulfilled_future_on

### .any_fulfilled_future_on(default_executor, *futures_and_or_events) ⇒ `Future` Originally defined in module FactoryMethods

Creates new future which is resolved after first of futures_and_or_events is fulfilled. Its result equals result of the first resolved future or if all futures_and_or_events reject, it has reason of the last resolved future. If resolved it does not propagate AbstractEventFuture#touch, leaving delayed futures un-executed if they are not required any more. If event is supplied, which does not have value and can be only resolved, it's represented as `:fulfilled` with value `nil`.

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- futures_and_or_events (`AbstractEventFuture`)

Returns:

- (`Future`)

### .any_resolved_future(*futures_and_or_events) ⇒ `Future` Also known as: any Originally defined in module FactoryMethods

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

Returns:

- (`Future`)

See Also:

- #any_resolved_future_on

### .any_resolved_future_on(default_executor, *futures_and_or_events) ⇒ `Future` Originally defined in module FactoryMethods

Creates new future which is resolved after first futures_and_or_events is resolved. Its result equals result of the first resolved future. If resolved it does not propagate AbstractEventFuture#touch, leaving delayed futures un-executed if they are not required any more. If event is supplied, which does not have value and can be only resolved, it's represented as `:fulfilled` with value `nil`.

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- futures_and_or_events (`AbstractEventFuture`)

Returns:

- (`Future`)

### .default_executor ⇒ `Executor`, `:io`, `:fast` Originally defined in module FactoryMethods::Configuration

Returns the executor which is used when none is supplied to a factory method. The method can be overridden in the receivers of `include FactoryMethod`

Returns:

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

  the executor which is used when none is supplied to a factory method. The method can be overridden in the receivers of `include FactoryMethod`

### .delay(*args, &task) ⇒ `Future` Originally defined in module FactoryMethods

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

Returns:

- (`Future`)

See Also:

- #delay_on

### .delay_on(default_executor, *args) {|*args| ... } ⇒ `Future` Originally defined in module FactoryMethods

Constructs new Future which will be resolved after block is evaluated on default executor. The task will be evaluated only after the future is touched, see AbstractEventFuture#touch

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- 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:

- (`*args`) —

  to the task.

Yield Returns:

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

Returns:

- (`Future`)

### .fulfilled_future(value, default_executor = self.default_executor) ⇒ `Future` Originally defined in module FactoryMethods

Creates resolved future with will be fulfilled with the given value.

Parameters:

- default_executor (`Executor`, `:io`, `:fast`) (defaults to: `self.default_executor`) —

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

Returns:

- (`Future`)

### .future(*args, &task) ⇒ `Future` Originally defined in module FactoryMethods

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

Returns:

- (`Future`)

See Also:

- #future_on

### .future_on(default_executor, *args) {|*args| ... } ⇒ `Future` Originally defined in module FactoryMethods

Constructs new Future which will be resolved after block is evaluated on default executor. Evaluation begins immediately.

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- 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:

- (`*args`) —

  to the task.

Yield Returns:

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

Returns:

- (`Future`)

### #create(nil, default_executor = self.default_executor) ⇒ `Event` #create(a_future, default_executor = self.default_executor) ⇒ `Future` #create(an_event, default_executor = self.default_executor) ⇒ `Event` #create(exception, default_executor = self.default_executor) ⇒ `Future` #create(value, default_executor = self.default_executor) ⇒ `Future` Originally defined in module FactoryMethods

General constructor. Behaves differently based on the argument's type. It's provided for convenience but it's better to be explicit.

Overloads:

- #create(nil, default_executor = self.default_executor) ⇒ `Event`

  Returns resolved event.

  Parameters:

  - nil (`nil`)

  Returns:

  - (`Event`) —

    resolved event.

- #create(a_future, default_executor = self.default_executor) ⇒ `Future`

  Returns a future which will be resolved when a_future is.

  Parameters:

  - a_future (`Future`)

  Returns:

  - (`Future`) —

    a future which will be resolved when a_future is.

- #create(an_event, default_executor = self.default_executor) ⇒ `Event`

  Returns an event which will be resolved when an_event is.

  Parameters:

  - an_event (`Event`)

  Returns:

  - (`Event`) —

    an event which will be resolved when an_event is.

- #create(exception, default_executor = self.default_executor) ⇒ `Future`

  Returns a rejected future with the exception as its reason.

  Parameters:

  - exception (`Exception`)

  Returns:

  - (`Future`) —

    a rejected future with the exception as its reason.

- #create(value, default_executor = self.default_executor) ⇒ `Future`

  Returns a fulfilled future with the value.

  Parameters:

  - value (`Object`) —

    when none of the above overloads fits

  Returns:

  - (`Future`) —

    a fulfilled future with the value.

Parameters:

- default_executor (`Executor`, `:io`, `:fast`) (defaults to: `self.default_executor`) —

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

Returns:

- (`Event`, `Future`)

See Also:

- resolved_event, fulfilled_future

### .rejected_future(reason, default_executor = self.default_executor) ⇒ `Future` Originally defined in module FactoryMethods

Creates resolved future with will be rejected with the given reason.

Parameters:

- default_executor (`Executor`, `:io`, `:fast`) (defaults to: `self.default_executor`) —

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

Returns:

- (`Future`)

### .resolvable_event ⇒ `ResolvableEvent` Originally defined in module FactoryMethods

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

Returns:

- (`ResolvableEvent`)

See Also:

- #resolvable_event_on

### .resolvable_event_on(default_executor = self.default_executor) ⇒ `ResolvableEvent` Originally defined in module FactoryMethods

Created resolvable event, user is responsible for resolving the event once by ResolvableEvent#resolve.

Parameters:

- default_executor (`Executor`, `:io`, `:fast`) (defaults to: `self.default_executor`) —

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

Returns:

- (`ResolvableEvent`)

### .resolvable_future ⇒ `ResolvableFuture` Originally defined in module FactoryMethods

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

Returns:

- (`ResolvableFuture`)

See Also:

- #resolvable_future_on

### .resolvable_future_on(default_executor = self.default_executor) ⇒ `ResolvableFuture` Originally defined in module FactoryMethods

Creates resolvable future, user is responsible for resolving the future once by ResolvableFuture#resolve, ResolvableFuture#fulfill, or ResolvableFuture#reject

Parameters:

- default_executor (`Executor`, `:io`, `:fast`) (defaults to: `self.default_executor`) —

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

Returns:

- (`ResolvableFuture`)

### .resolved_event(default_executor = self.default_executor) ⇒ `Event` Originally defined in module FactoryMethods

Creates resolved event.

Parameters:

- default_executor (`Executor`, `:io`, `:fast`) (defaults to: `self.default_executor`) —

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

Returns:

- (`Event`)

### .resolved_future(fulfilled, value, reason, default_executor = self.default_executor) ⇒ `Future` Originally defined in module FactoryMethods

Creates resolved future with will be either fulfilled with the given value or rejection with the given reason.

Parameters:

- default_executor (`Executor`, `:io`, `:fast`) (defaults to: `self.default_executor`) —

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

Returns:

- (`Future`)

### .schedule(intended_time, *args, &task) ⇒ `Future` Originally defined in module FactoryMethods

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

Returns:

- (`Future`)

See Also:

- #schedule_on

### .schedule_on(default_executor, intended_time, *args) {|*args| ... } ⇒ `Future` Originally defined in module FactoryMethods

Constructs new Future which will be resolved after block is evaluated on default executor. The task is planned for execution in intended_time.

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- args (`Object`) —

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

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

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

Yields:

- (`*args`) —

  to the task.

Yield Returns:

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

Returns:

- (`Future`)

### .select_channel(*channels) ⇒ `Future` Originally defined in module FactoryMethods::NewChannelIntegration

Selects a channel which is ready to be read from.

Parameters:

- channels (`Channel`)

Returns:

- (`Future`) —

  a future which is fulfilled with pair [channel, message] when one of the channels is available for reading

### .zip_events(*futures_and_or_events) ⇒ `Event` Originally defined in module FactoryMethods

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

Returns:

- (`Event`)

See Also:

- #zip_events_on

### .zip_events_on(default_executor, *futures_and_or_events) ⇒ `Event` Originally defined in module FactoryMethods

Creates new event which is resolved after all futures_and_or_events are resolved. (Future is resolved when fulfilled or rejected.)

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- futures_and_or_events (`AbstractEventFuture`)

Returns:

- (`Event`)

### .zip_futures(*futures_and_or_events) ⇒ `Future` Also known as: zip Originally defined in module FactoryMethods

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

Returns:

- (`Future`)

See Also:

- #zip_futures_on

### .zip_futures_on(default_executor, *futures_and_or_events) ⇒ `Future` Originally defined in module FactoryMethods

Creates new future which is resolved after all futures_and_or_events are resolved. Its value is array of zipped future values. Its reason is array of reasons for rejection. If there is an error it rejects. If event is supplied, which does not have value and can be only resolved, it's represented as `:fulfilled` with value `nil`.

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- futures_and_or_events (`AbstractEventFuture`)

Returns:

- (`Future`)

### .zip_futures_over(enumerable, &future_factory) ⇒ `Future` Originally defined in module FactoryMethods

Note:

Edge Features are under active development and may change frequently.

- Deprecations are not added before incompatible changes.
- Edge version: major is always 0, minor bump means incompatible change, patch bump means compatible change.
- Edge features may also lack tests and documentation.
- Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when finalised.

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

Returns:

- (`Future`)

See Also:

- #zip_futures_over_on

### .zip_futures_over_on(default_executor, enumerable) {|element| ... } ⇒ `Future` Originally defined in module FactoryMethods

Note:

Edge Features are under active development and may change frequently.

- Deprecations are not added before incompatible changes.
- Edge version: major is always 0, minor bump means incompatible change, patch bump means compatible change.
- Edge features may also lack tests and documentation.
- Features developed in `concurrent-ruby-edge` are expected to move to `concurrent-ruby` when finalised.

Creates new future which is resolved after all the futures created by future_factory from enumerable elements are resolved. Simplified it does: `zip(*enumerable.map { |e| future e, &future_factory })`

Examples:

    # `#succ` calls are executed in parallel
    zip_futures_over_on(:io, [1, 2], &:succ).value! # => [2, 3]

Parameters:

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

  Instance of an executor or a name of the global executor. Default executor propagates to chained futures unless overridden with executor parameter or changed with AbstractEventFuture#with_default_executor.

- enumerable (`Enumerable`)

Yields:

- a task to be executed in future

Yield Parameters:

- element (`Object`) —

  from enumerable

Yield Returns:

- (`Object`) —

  a value of the future

Returns:

- (`Future`)