/* * 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>