proxygen
folly::Promise< T > Class Template Reference

#include <Future-pre.h>

Public Member Functions

 Promise ()
 
 ~Promise ()
 
 Promise (Promise const &)=delete
 
Promiseoperator= (Promise const &)=delete
 
 Promise (Promise< T > &&other) noexcept
 
Promiseoperator= (Promise< T > &&other) noexcept
 
SemiFuture< TgetSemiFuture ()
 
Future< TgetFuture ()
 
void setException (exception_wrapper ew)
 
template<class E >
std::enable_if< std::is_base_of< std::exception, E >::value >::type setException (E const &e)
 
template<typename F >
void setInterruptHandler (F &&fn)
 
template<class B = T>
std::enable_if< std::is_same< Unit, B >::value, void >::type setValue ()
 
template<class M >
void setValue (M &&value)
 
void setTry (Try< T > &&t)
 
template<class F >
void setWith (F &&func)
 
bool valid () const noexcept
 
bool isFulfilled () const noexcept
 

Static Public Member Functions

static Promise< TmakeEmpty () noexcept
 

Private Types

using Core = futures::detail::Core< T >
 

Private Member Functions

CoregetCore ()
 
Core const & getCore () const
 
 Promise (futures::detail::EmptyConstruct) noexcept
 
void throwIfFulfilled () const
 
void detach ()
 

Static Private Member Functions

template<typename CoreT >
static CoreT & getCoreImpl (CoreT *core)
 

Private Attributes

bool retrieved_
 
Corecore_
 

Friends

template<class >
class futures::detail::FutureBase
 
template<class >
class SemiFuture
 
template<class >
class Future
 
template<class , class >
class futures::detail::CoreCallbackState
 

Detailed Description

template<class T>
class folly::Promise< T >

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.

Definition at line 23 of file Future-pre.h.

Member Typedef Documentation

template<class T>
using folly::Promise< T >::Core = futures::detail::Core<T>
private

Definition at line 414 of file Promise.h.

Constructor & Destructor Documentation

template<class T >
folly::Promise< T >::Promise ( )

Constructs a valid but unfulfilled promise.

Postconditions:

  • valid() == true (it will have a shared state)
  • isFulfilled() == false (its shared state won't have a result)

Definition at line 45 of file Promise-inl.h.

45 : retrieved_(false), core_(Core::make()) {}
Core * core_
Definition: Promise.h:438
bool retrieved_
Definition: Promise.h:412
static Core * make()
State will be Start.
Definition: Core.h:205
template<class T >
folly::Promise< T >::~Promise ( )

Postconditions:

  • If valid() and !isFulfilled(), the associated future (if any) will be completed with a BrokenPromise exception as if by setException(...).
  • If valid(), releases, possibly destroying, the shared state.

Definition at line 72 of file Promise-inl.h.

References folly::Promise< T >::detach().

72  {
73  detach();
74 }
template<class T>
folly::Promise< T >::Promise ( Promise< T > const &  )
delete
template<class T>
folly::Promise< T >::Promise ( Promise< T > &&  other)
noexcept

Move ctor

Postconditions:

  • this will have whatever shared-state was previously held by other (if any)
  • other.valid() will be false (other will not have any shared state)

Definition at line 48 of file Promise-inl.h.

49  : retrieved_(exchange(other.retrieved_, false)),
50  core_(exchange(other.core_, nullptr)) {}
Core * core_
Definition: Promise.h:438
T exchange(T &obj, U &&new_value)
Definition: Utility.h:120
bool retrieved_
Definition: Promise.h:412
template<class T>
folly::Promise< T >::Promise ( futures::detail::EmptyConstruct  )
explicitprivatenoexcept

Definition at line 68 of file Promise-inl.h.

69  : retrieved_(false), core_(nullptr) {}
Core * core_
Definition: Promise.h:438
bool retrieved_
Definition: Promise.h:412

Member Function Documentation

template<class T >
void folly::Promise< T >::detach ( )
private
template<class T>
Core& folly::Promise< T >::getCore ( )
inlineprivate

Definition at line 421 of file Promise.h.

Referenced by folly::Promise< T >::getSemiFuture(), folly::Promise< T >::setInterruptHandler(), and folly::Promise< T >::throwIfFulfilled().

421  {
422  return getCoreImpl(core_);
423  }
static CoreT & getCoreImpl(CoreT *core)
Definition: Promise.h:429
Core * core_
Definition: Promise.h:438
template<class T>
Core const& folly::Promise< T >::getCore ( ) const
inlineprivate

Definition at line 424 of file Promise.h.

424  {
425  return getCoreImpl(core_);
426  }
static CoreT & getCoreImpl(CoreT *core)
Definition: Promise.h:429
Core * core_
Definition: Promise.h:438
template<class T>
template<typename CoreT >
static CoreT& folly::Promise< T >::getCoreImpl ( CoreT *  core)
inlinestaticprivate

Definition at line 429 of file Promise.h.

429  {
430  if (!core) {
431  throw_exception<PromiseInvalid>();
432  }
433  return *core;
434  }
template<class T >
Future< T > folly::Promise< T >::getFuture ( )

Return a Future associated with this Promise, sharing the same shared state as this.

Preconditions:

Postconditions:

  • RESULT.valid() == true
  • RESULT will share the same shared-state as this

DEPRECATED: use folly::makePromiseContract() instead. If you can't use that, use this->getSemiFuture() then get a Future by calling .via() with an appropriate executor.

Definition at line 97 of file Promise-inl.h.

References folly::Promise< T >::getSemiFuture(), folly::InlineExecutor::instance(), type, and value.

Referenced by folly::fibers::BatchDispatcher< ValueT, ResultT, ExecutorT >::add(), folly::FutureExecutor< ExecutorImpl >::addFuture(), folly::fibers::FiberManager::addTaskFuture(), folly::fibers::FiberManager::addTaskRemoteFuture(), wangle::TimekeeperTester::after(), wangle::TimekeeperTester::at(), BENCHMARK_RELATIVE(), wangle::ClientBootstrap< DefaultPipeline >::connect(), fGen(), folly::python::test::future_getValueX5(), folly::AttachDetachClient::getFuture(), wangle::PipelinedClientDispatcher< Pipeline, Req, Resp >::operator()(), HTTPDownstreamTest< SPDY3_1CodecPair >::sendRequestLater(), TEST(), TEST_F(), fizz::server::test::TEST_F(), fizz::test::TEST_F(), and folly::unorderedReduce().

97  {
98  // An InlineExecutor approximates the old behaviour of continuations
99  // running inine on setting the value of the promise.
100  return getSemiFuture().via(&InlineExecutor::instance());
101 }
FOLLY_ATTR_VISIBILITY_HIDDEN static FOLLY_ALWAYS_INLINE InlineExecutor & instance() noexcept
SemiFuture< T > getSemiFuture()
Definition: Promise-inl.h:88
template<class T >
SemiFuture< T > folly::Promise< T >::getSemiFuture ( )

Return a SemiFuture associated with this Promise, sharing the same shared state as this.

Preconditions:

Postconditions:

  • RESULT.valid() == true
  • RESULT will share the same shared-state as this

DEPRECATED: use folly::makePromiseContract() instead.

Definition at line 88 of file Promise-inl.h.

References folly::Promise< T >::getCore(), and folly::Promise< T >::retrieved_.

Referenced by folly::futures::detail::chainExecutor(), folly::collectAny(), folly::Promise< T >::getFuture(), folly::Future< T >::onError(), folly::Future< T >::onTimeout(), TEST(), folly::futures::detail::FutureBase< T >::thenImplementation(), folly::Future< T >::via(), folly::SemiFuture< T >::wait(), and folly::futures::detail::waitImpl().

88  {
89  if (retrieved_) {
90  throw_exception<FutureAlreadyRetrieved>();
91  }
92  retrieved_ = true;
93  return SemiFuture<T>(&getCore());
94 }
Core & getCore()
Definition: Promise.h:421
bool retrieved_
Definition: Promise.h:412
template<class T >
bool folly::Promise< T >::isFulfilled ( ) const
noexcept

True if either this promise was fulfilled or is invalid.

Definition at line 143 of file Promise-inl.h.

References folly::Promise< T >::core_, and folly::futures::detail::Core< T >::hasResult().

Referenced by TEST().

143  {
144  if (core_) {
145  return core_->hasResult();
146  }
147  return true;
148 }
Core * core_
Definition: Promise.h:438
bool hasResult() const noexcept
Definition: Core.h:242
template<class T >
Promise< T > folly::Promise< T >::makeEmpty ( )
staticnoexcept

Returns an invalid promise.

Postconditions:

  • RESULT.valid() == false
  • RESULT.isFulfilled() == true

Definition at line 40 of file Promise-inl.h.

Referenced by TEST().

40  {
41  return Promise<T>(futures::detail::EmptyConstruct{});
42 }
template<class T>
Promise& folly::Promise< T >::operator= ( Promise< T > const &  )
delete
template<class T>
Promise< T > & folly::Promise< T >::operator= ( Promise< T > &&  other)
noexcept

Move assignment

Postconditions:

  • If valid() and !isFulfilled(), the associated future (if any) will be completed with a BrokenPromise exception as if by setException(...).
  • If valid(), releases, possibly destroying, the original shared state.
  • this will have whatever shared-state was previously held by other (if any)
  • other.valid() will be false (other will not have any shared state)

Definition at line 53 of file Promise-inl.h.

References folly::Promise< T >::core_, folly::Promise< T >::detach(), folly::exchange(), and folly::Promise< T >::retrieved_.

53  {
54  detach();
55  retrieved_ = exchange(other.retrieved_, false);
56  core_ = exchange(other.core_, nullptr);
57  return *this;
58 }
Core * core_
Definition: Promise.h:438
T exchange(T &obj, U &&new_value)
Definition: Utility.h:120
bool retrieved_
Definition: Promise.h:412
template<class T >
void folly::Promise< T >::setException ( exception_wrapper  ew)

Fulfill the Promise with an exception_wrapper.

Sample usage:

Promise<MyValue> p = ... ... auto const ep = std::exception_ptr(); auto const ew = exception_wrapper::from_exception_ptr(ep); p.setException(ew);

Functionally equivalent to setTry(Try<T>(std::move(ew)))

Preconditions:

Postconditions:

  • isFulfilled() == true
  • valid() == true (unchanged)
  • The associated future (if any) will complete with the exception.

Definition at line 111 of file Promise-inl.h.

References folly::gen::move, and folly::Promise< T >::setTry().

Referenced by folly::AttachDetachClient::readErr(), folly::Promise< T >::setException(), TEST(), TEST_F(), and wangle::AsyncSocketHandler::WriteCallback::writeErr().

111  {
112  setTry(Try<T>(std::move(ew)));
113 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void setTry(Try< T > &&t)
Definition: Promise-inl.h:122
template<class T >
template<class E >
std::enable_if< std::is_base_of< std::exception, E >::value >::type folly::Promise< T >::setException ( E const &  e)

Fulfill the Promise with exception e as if by setException(make_exception_wrapper<E>(e)).

Please see setException(exception_wrapper) for semantics/contract.

Definition at line 106 of file Promise-inl.h.

References folly::Promise< T >::setException().

106  {
107  setException(make_exception_wrapper<E>(e));
108 }
void setException(exception_wrapper ew)
Definition: Promise-inl.h:111
template<class T >
template<typename F >
void folly::Promise< T >::setInterruptHandler ( F &&  fn)

Sets a handler for the producer to receive a (logical) interruption request (exception) sent from the consumer via future.raise().

Details: The consumer calls future.raise() when it wishes to send a logical interruption message (an exception), and that exception/message is passed to fn(). The thread used to call fn() depends on timing (see Postconditions for threading details).

Handler fn() can do anything you want, but if you bother to set one then you probably will want to (more or less immediately) fulfill the promise with an exception (or other special value) indicating how the interrupt was handled.

This call silently does nothing if isFulfilled().

Preconditions:

  • valid() == true (else throws PromiseInvalid)
  • fn must be copyable and must be invocable with exception_wrapper const&
  • the code within fn() must be safe to run either synchronously within the setInterruptHandler() call or asynchronously within the consumer thread's call to future.raise().
  • the code within fn() must also be safe to run after this promise is fulfilled; this may have lifetime/race-case ramifications, e.g., if the code of fn() might access producer-resources that will be destroyed, then the destruction of those producer-resources must be deferred beyond the moment when this promise is fulfilled.

Postconditions:

  • if the consumer calls future.raise() early enough (up to a particular moment within the setInterruptHandler() call), fn() will be called synchronously (in the current thread, during this call).
  • if the consumer calls future.raise() after that moment within setInterruptHandler() but before this promise is fulfilled, fn() will be called asynchronously (in the consumer's thread, within the call to future.raise()).
  • if the consumer calls future.raise() after this promise is fulfilled, fn() may or may not be called at all, and if it is called, it will be called asynchronously (within the consumer's call to future.raise()).

IMPORTANT: fn() should return quickly since it could block this call to promise.setInterruptHandler() and/or a concurrent call to future.raise(). Those two functions contend on the same lock; those calls could block if fn() is invoked within one of those while the lock is held.

Definition at line 117 of file Promise-inl.h.

References folly::Promise< T >::getCore(), and folly::futures::detail::Core< T >::setInterruptHandler().

Referenced by TEST().

117  {
118  getCore().setInterruptHandler(std::forward<F>(fn));
119 }
void setInterruptHandler(F &&fn)
Definition: Core.h:483
Core & getCore()
Definition: Promise.h:421
template<class T>
void folly::Promise< T >::setTry ( Try< T > &&  t)
template<class T>
template<class B = T>
std::enable_if<std::is_same<Unit, B>::value, void>::type folly::Promise< T >::setValue ( )
inline

Fulfills a (logically) void Promise, that is, Promise<Unit>. (If you want a void-promise, use Promise<Unit>, not Promise<void>.)

Preconditions:

Postconditions:

Definition at line 326 of file Promise.h.

Referenced by BENCHMARK_RELATIVE(), fGen(), folly::AttachDetachClient::readDataAvailable(), TEST(), TEST_F(), fizz::server::test::TEST_F(), fizz::test::TEST_F(), and wangle::AsyncSocketHandler::WriteCallback::writeSuccess().

326  {
327  setTry(Try<T>(T()));
328  }
folly::std T
void setTry(Try< T > &&t)
Definition: Promise-inl.h:122
template<class T >
template<class M >
void folly::Promise< T >::setValue ( M &&  value)

Fulfill the Promise with the specified value using perfect forwarding.

Functionally equivalent to setTry(Try<T>(std::forward<M>(value)))

Preconditions:

Postconditions:

  • isFulfilled() == true
  • valid() == true (unchanged)
  • The associated future will see the value, e.g., in its continuation.

Definition at line 129 of file Promise-inl.h.

References folly::Promise< T >::setTry(), and value.

129  {
130  static_assert(!std::is_same<T, void>::value, "Use setValue() instead");
131 
132  setTry(Try<T>(std::forward<M>(v)));
133 }
void setTry(Try< T > &&t)
Definition: Promise-inl.h:122
static const char *const value
Definition: Conv.cpp:50
template<class T >
template<class F >
void folly::Promise< T >::setWith ( F &&  func)

Fulfill this Promise with the result of a function that takes no arguments and returns something implicitly convertible to T.

Example:

p.setWith([] { do something that may throw; return a T; });

Functionally equivalent to setTry(makeTryWith(static_cast<F&&>(func)));

Preconditions:

Postconditions:

  • func() will be run synchronously (in this thread, during this call)
  • If func() returns, the return value will be captured as if via setValue()
  • If func() throws, the exception will be captured as if via setException()
  • isFulfilled() == true
  • valid() == true (unchanged)
  • The associated future will see the result, e.g., in its continuation.

Definition at line 137 of file Promise-inl.h.

References folly::makeTryWith(), folly::Promise< T >::setTry(), and folly::Promise< T >::throwIfFulfilled().

Referenced by folly::FutureExecutor< ExecutorImpl >::addFuture(), folly::python::test::future_getValueX5(), and TEST().

137  {
139  setTry(makeTryWith(std::forward<F>(func)));
140 }
void throwIfFulfilled() const
Definition: Promise-inl.h:61
void setTry(Try< T > &&t)
Definition: Promise-inl.h:122
std::enable_if< !std::is_same< invoke_result_t< F >, void >::value, Try< invoke_result_t< F > > >::type makeTryWith(F &&f)
Definition: Try-inl.h:223
template<class T >
void folly::Promise< T >::throwIfFulfilled ( ) const
private

Definition at line 61 of file Promise-inl.h.

References folly::Promise< T >::getCore().

Referenced by folly::Promise< T >::setTry(), and folly::Promise< T >::setWith().

61  {
62  if (getCore().hasResult()) {
63  throw_exception<PromiseAlreadySatisfied>();
64  }
65 }
Core & getCore()
Definition: Promise.h:421
template<class T>
bool folly::Promise< T >::valid ( ) const
inlinenoexcept

true if this has a shared state; false if this has been consumed/moved-out.

Definition at line 390 of file Promise.h.

390  {
391  return core_ != nullptr;
392  }
Core * core_
Definition: Promise.h:438

Friends And Related Function Documentation

template<class T>
template<class >
friend class Future
friend

Definition at line 407 of file Promise.h.

template<class T>
template<class , class >
friend class futures::detail::CoreCallbackState
friend

Definition at line 409 of file Promise.h.

template<class T>
template<class >
friend class futures::detail::FutureBase
friend

Definition at line 403 of file Promise.h.

template<class T>
template<class >
friend class SemiFuture
friend

Definition at line 405 of file Promise.h.

Member Data Documentation

template<class T>
bool folly::Promise< T >::retrieved_
private

The documentation for this class was generated from the following files: