folly/folly/futures/Promise.h

/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <array>
#include <functional>

#include <folly/Portability.h>
#include <folly/Try.h>
#include <folly/futures/detail/Core.h>
#include <folly/lang/Exception.h>
#include <folly/lang/Pretty.h>

namespace folly {

class FOLLY_EXPORT PromiseException : public std::logic_error {};

class FOLLY_EXPORT PromiseInvalid : public PromiseException {};

class FOLLY_EXPORT PromiseAlreadySatisfied : public PromiseException {};

class FOLLY_EXPORT FutureAlreadyRetrieved : public PromiseException {};

class FOLLY_EXPORT BrokenPromise : public PromiseException {};

// forward declaration
template <class T>
class SemiFuture;
template <class T>
class Future;
template <class T>
class Promise;

namespace futures {
namespace detail {
class FutureBaseHelper;
template <class T>
class FutureBase;
struct EmptyConstruct {};
template <typename T, typename F>
class CoreCallbackState;
template <typename T>
void setTry(Promise<T>& p, Executor::KeepAlive<>&& ka, Try<T>&& t);

struct MakeRetrievedFromStolenCoreTag {};
} // namespace detail
} // namespace futures

/// Promises and futures provide a potentially nonblocking mechanism
///   to execute a producer/consumer operation concurrently, with
///   threading/pools controlled via an executor. There are multiple potential
///   patterns for using promises and futures including some that block the
///   caller, though that is discouraged; it should be used only when necessary.
///
/// One typical pattern uses a series of calls to set up a small, limited
///   program that...
///
/// - ...performs the desired operations (based on a lambda)...
/// - ...on an asynchronously provided input (an exception or a value)...
/// - ...lazily, when that input is ready (without blocking the caller)...
/// - ...using appropriate execution resources (determined by the executor)...
/// - ...then after constructing the 'program,' launches the asynchronous
///   producer.
///
/// That usage pattern looks roughly like this:
///
///   auto [p, f] = makePromiseContract(executor);
///   g = std::move(f).then([](MyValue&& x) {
///       ...executor runs this code if/when a MyValue is ready...
///     });
///   ...launch the async producer that eventually calls p.setResult()...
///
/// This is just one of many potential usage patterns. It has the desired
/// property of being nonblocking to the caller. Of course the `.then()`
/// code is deferred until the produced value (or exception) is ready,
/// but no code actually blocks pending completion of other operations.
///
/// The promise/future mechanism is limited to a single object of some arbitrary
/// type. It also supports a (logically) void result, i.e., in cases where the
/// continuation/consumer (the `.then()` code if using the above pattern) is not
/// expecting a value because the 'producer' is running for its side-effects.
///
/// The primary data movement is from producer to consumer, however Promise and
/// Future also provide a mechanism where the consumer can send an interruption
/// message to the producer. The meaning and response to that interruption
/// message is controlled by the promise; see `Promise::setInterruptHandler()`.
///
/// Neither Promise nor Future is thread-safe. All internal interactions
/// between a promise and its associated future are thread-safe, provided that
/// callers otherwise honor the promise's contract and the future's contract.
///
/// Logically there are up to three threads (though in practice there are often
/// fewer - one thread might take on more than one role):
///
/// - Set-up thread: thread used to construct the Promise, and often also to
///   set up the SemiFuture/Future.
/// - Producer thread: thread that produces the result.
/// - Consumer thread: thread in which the continuation is invoked (a
///   continuation is a callback provided to `.then` or to a variant).
///
/// For description purposes, the term 'shared state' is used to describe the
///   logical state shared by the promise and the future. This 'third object'
///   represents things like whether the result has been fulfilled, the value or
///   exception in that result, and the data needed to handle interruption
///   requests.
///
/// A promise can be in various logical states:
///
/// - valid vs. invalid (has vs. does not have a shared state, respectfully).
/// - fulfilled vs. unfulfilled (an invalid promise is always fulfilled; a valid
///   promise is fulfilled if the shared-state has a result).
///
/// A promise `p` may optionally have an associated future. This future, if it
///   exists, may be either a SemiFuture or a Future, and is defined as the
///   future (if any) that holds the same shared state as promise `p`.
///   The associated future is initially the future returned from
///   `p.getFuture()` or `p.getSemiFuture()`, but various operations
///   may transfer the shared state from one future to another.
template <class T>
class Promise {};

} // namespace folly

#include <folly/futures/Future.h>
#include <folly/futures/Promise-inl.h>