#include "tensorstore/util/future.h"
template <typename T>
class [[nodiscard]] tensorstore::Future : public AnyFuture;

“Consumer” interface to a one-time channel.

Future<T> provides an interface for a consumer to asynchronously receive a value of type T or an error through a Result<T>.

In typical use, a consumer uses the Future::ExecuteWhenReady method to register a callback to be invoked when the shared state becomes ready. Alternatively, Future::result may be called to synchronously wait for the result, blocking the current thread.

Promise<T> provides an interface for a producer to asynchronously send a value of type T or an error through a Result<T>.

In typical usage, an asynchronous operation initiator will create paired Future<T> and Promise<T> objects by invoking PromiseFuturePair<T>::Make(). From there, the asynchronous operation which returns a T can be installed on the Promise<>, typically putting the operation and the promise onto an executor or other thread pool, and storing the result of the operation on the promise, while returning the Future<> to the caller.

Both Promise<void> and Future<void> are supported and return a Result<void>.

Promise<T> and Future<T> behave like reference counted pointers to a shared state that stores the actual value. In normal usage, there will be one or more instances of Promise<T>, and one or more instances of Future<T>, all referring to the same shared state. The shared state is initially marked “not ready”, and transitions to the “ready” state when a producer sets the result. Once the state becomes “ready”, it cannot become “not ready”, and any further attempts to set the value have no effect.

A limited form of cancellation is supported. Cancellation is signalled when all Future<T> instances referencing the shared state are destroyed or go out of scope before the operation completes. Using the Promise::ExecuteWhenNotNeeded method, a producer may register callbacks to be invoked when either the shared state becomes ready or there are no more futures referencing the shared state.

In addition to the producer -> consumer communication of a value or error, a limited form of consumer -> producer communication is also supported: a producer may defer performing certain work until the result is actually required. For example, this is useful if the deferred work may never be needed, or multiple deferred work items may be more efficiently handled together as a batch. On the consumer side, this is handled by the Future::Force method that may be invoked manually to indicate that the result is needed, and is also invoked automatically when a thread synchronously waits for the result. This calls any callbacks that a producer has registered using the Promise::ExecuteWhenForced method.

This Promise/Future implementation is executor-agnostic: all callbacks that are registered are either invoked immediately before the registration function returns (if the condition is already satisfied), or immediately by the thread that causes the condition to be satisfied (e.g. calling Promise::SetResult, Future::Force, or destroying the last Future or Promise referencing a given shared state). Therefore, the callbacks that are registered should not block or perform expensive computations; instead, any blocking or expensive computations should either be somehow deferred or run asynchronously on another thread. In addition, actions such as calling Promise::SetResult, Future::Force, and destroying a Promise or Future object should not be done while holding any exclusive locks that may be needed by a callback.

Examples:

// Runs `function` asynchronously using `executor`, and returns a Future
// representing the return value of `function`.
template <typename T>
Future<T> RunAsync(std::function<T()> function, Executor executor) {
  auto pair = PromiseFuturePair<T>::Make();
  executor([promise = std::move(pair.promise),
            function = std::move(function)] {
    promise.SetResult(function());
  });
  return std::move(pair.future);
}
Future<void> future = RunAsync([]->void {
    std::count << " Async! " << std::endl;
}, executor);
future.Wait();

// Like `RunAsync`, except execution of `function` is deferred until
// Force is called on the returned Future.
template <typename T>
Future<T> RunDeferred(std::function<T()> function, Executor executor) {
  auto pair = PromiseFuturePair<T>::Make();
  pair.promise.ExecuteWhenForced([promise = std::move(pair.promise),
                                  function = std::move(function),
                                  executor = std::move(executor)] {
    executor([promise = std::move(promise),
              function = std::move(function)] {
      promise.SetResult(function());
    });
  });
  return std::move(pair.future);
}

// Returns a Future representing the asynchronous addition of
// `a.value()` and `b.value()`.
Future<int> AddAsync1(Future<int> a, Future<int> b) {
  return PromiseFuturePair<int>::LinkValue(
    [](Promise<int> c, Future<int> a, Future<int> b) {
      c.SetResult(MapResult(std::plus<int>{}, a.result(), b.result()));
    }, std::move(a), std::move(b)).future;
}

// Equivalent to `AddAsync1`, showing usage of `MapFutureValue`.
Future<int> AddAsync2(Future<int> a, Future<int> b) {
  return MapFutureValue(InlineExecutor{},
                        std::plus<int>{}, std::move(a), std::move(b));
}

// Synchronously adds `a.value()` and `b.value()`.
Result<int> AddSync1(Future<int> a, Future<int> b) {
  // In case `a` and `b` represent deferred computations, call Force on
  // both before blocking via `result()` to allow both computations to
  // run in parallel.
  a.Force();
  b.Force();
  return MapResult(std::plus<int>{}, a.result(), b.result());
}

// Equivalent to `AddSync1`, showing how a Future-returning function can
// be used synchronously.
Result<int> AddSync2(Future<int> a, Future<int> b) {
  return AddAsync2(a, b).result();
}
Template Parameters:
typename T

Specifies the type of the value to be transmitted. The actual result value type is Result<std::remove_const_t<T>>.

Types

type result_type;

The result type transmitted by the channel.

using value_type = T;

The value type contained in the result_type.

Constructors

Future();

Constructs an null Future.

Future(Future<U> x);

Constructs from a compatible Future.

Future(const Result<Future<U>>result);

Constructs a Future from a Result<Future<U>>, where U is T or const U is T.

Future(const absl::Statusstatus);
Future(absl::Status&status);

Construct a Future<T> with an an absl::Status code.

Future(const Result<U>result);
Future(Result<U>&result);

Construct a Future<T> from a Result<U>.

Future(V&value);

Construct a Future<T> from a value convertible to a Result<T>.

Methods

Futureoperator=(Future<U> x) noexcept;

Assigns from a compatible Future.

void IgnoreFuture() const;

Ignores the future. This method signals intent to ignore the result to suppress compiler warnings from [[nodiscard]].

FutureCallbackRegistration ExecuteWhenReady(Callback&callback) &&;
FutureCallbackRegistration
ExecuteWhenReady(Callback&callback) const&;

Registers a callback to invoke when ready() becomes true.

std::add_lvalue_reference_t<result_type> result() const;

Calls Force(), waits for the result to be ready, and returns a reference to the result.

std::add_lvalue_reference_t<T> value() const;

Equivalent to result().value().

constexpr bool tensorstore::IsFuture<T>;

Evaluates to true if T is an instance of Future.

constexpr bool tensorstore::IsFutureConvertible<SourceT, DestT>;

Bool-valued metafunction equal to true if, and only if, Future<SourceT> is convertible to Future<DestT>.

using tensorstore::UnwrapFutureType<T>;

Alias that maps Future<T>->T, Result<T>->T, or otherwise T->T.

class tensorstore::FutureCallbackRegistration;

Handle to a registered Future or Promise callback, that may be used to unregister it.

class [[nodiscard]] tensorstore::ReadyFuture<T> : public Future<T>;

Future that is guaranteed to be ready.

ReadyFuture<T> tensorstore::MakeReadyFuture(U&&... u);
ReadyFuture<const void> tensorstore::MakeReadyFuture();

Creates a Future in a ready state.

Future<void> tensorstore::WaitAllFuture(Futures&&... future);

Creates a future tied to the completion of all the provided future objects.

Future<void>
tensorstore::WaitAllFuture(span<const AnyFuture> futures);

Creates a Future tied to the completion of all the provided futures objects.

Linking

FutureCallbackRegistration
tensorstore::Link(Callback&callback,
                  
Promise<PromiseValue> promise,
                  
Futures&&... future);

Creates a “link”, which ties a promise to one or more future objects and a callback.

FutureCallbackRegistration
tensorstore::LinkValue(Callback&callback,
                       
Promise<PromiseValue> promise,
                       
Futures&&... future);

Creates a “link”, which ties a promise to one or more future objects and a callback.

FutureCallbackRegistration
tensorstore::LinkError(Promise<PromiseValue> promise,
                       
Futures&&... future);

Creates a “link”, which ties a promise to one or more future objects.

FutureCallbackRegistration
tensorstore::LinkResult(Promise<PromiseValue> promise,
                        
Future<FutureValue> future);

Creates a Link that moves a single Future’s result to a Promise.

Map functions

auto tensorstore::MapFuture(Executor&executor,
                            
Callback&callback,
                            
Future<FutureValue>... future);

Returns a Future that resolves to the result of calling callback(future.result()...) when all of the specified future objects become ready. The callback is invoked using the specified executor.

Future<UnwrapFutureType<std::remove_cvref_t<
    
std::invoke_result_t<Callback, FutureValue&...>>>>
tensorstore::MapFutureValue(Executor&executor,
                            
Callback&callback,
                            
Future<FutureValue>... future);

Returns a Future that resolves to callback(future.value()...) when all of the specified future objects become ready with non-error results. The callback is invoked using the specified executor.

Future<T> tensorstore::MapFutureError(Executor&executor,
                                      
Func func,
                                      
Future<T> future);

Transforms the error status of a Future.