proxygen
folly::futures::detail::FutureBase< T > Class Template Reference

#include <Future.h>

Inheritance diagram for folly::futures::detail::FutureBase< T >:
folly::Future< T > folly::SemiFuture< T > folly::Future< folly::folly::Unit >

Public Types

typedef T value_type
 

Public Member Functions

template<class T2 = T, typename = typename std::enable_if< !isFuture<typename std::decay<T2>::type>::value && !isSemiFuture<typename std::decay<T2>::type>::value>::type>
 FutureBase (T2 &&val)
 
template<class T2 = T>
 FutureBase (typename std::enable_if< std::is_same< Unit, T2 >::value >::type *)
 
template<class... Args, typename std::enable_if< std::is_constructible< T, Args &&... >::value, int >::type = 0>
 FutureBase (in_place_t, Args &&...args)
 
 FutureBase (FutureBase< T > const &)=delete
 
 FutureBase (SemiFuture< T > &&) noexcept
 
 FutureBase (Future< T > &&) noexcept
 
 FutureBase (Future< T > const &)=delete
 
 FutureBase (SemiFuture< T > const &)=delete
 
 ~FutureBase ()
 
bool valid () const noexcept
 
Tvalue ()&
 
T const & value () const &
 
T && value ()&&
 
T const && value () const &&
 
Try< T > & result ()&
 
Try< T > const & result () const &
 
Try< T > && result ()&&
 
Try< T > const && result () const &&
 
bool isReady () const
 
bool hasValue () const
 
bool hasException () const
 
Optional< Try< T > > poll ()
 
template<class F >
void setCallback_ (F &&func)
 
template<class F >
void setCallback_ (F &&func, std::shared_ptr< folly::RequestContext > context)
 
void raise (exception_wrapper interrupt)
 
template<class E >
void raise (E &&exception)
 
void cancel ()
 
int8_t getPriority () const
 

Protected Types

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

Protected Member Functions

CoregetCore ()
 
Core const & getCore () const
 
Try< T > & getCoreTryChecked ()
 
Try< T > const & getCoreTryChecked () const
 
 FutureBase (Core *obj)
 
 FutureBase (futures::detail::EmptyConstruct) noexcept
 
void detach ()
 
void throwIfInvalid () const
 
void throwIfContinued () const
 
void assign (FutureBase< T > &&other) noexcept
 
ExecutorgetExecutor () const
 
void setExecutor (Executor *x, int8_t priority=Executor::MID_PRI)
 
void setExecutor (Executor::KeepAlive<> x, int8_t priority=Executor::MID_PRI)
 
template<typename F , typename R >
std::enable_if<!R::ReturnsFuture::value, typename R::Return >::type thenImplementation (F &&func, R)
 
template<typename F , typename R >
std::enable_if< R::ReturnsFuture::value, typename R::Return >::type thenImplementation (F &&func, R)
 
template<typename E >
SemiFuture< TwithinImplementation (Duration dur, E e, Timekeeper *tk)&&
 

Static Protected Member Functions

template<typename Self >
static decltype(auto) getCoreImpl (Self &self)
 
template<typename Self >
static decltype(auto) getCoreTryChecked (Self &self)
 

Protected Attributes

Corecore_
 

Friends

class Promise< T >
 
template<class >
class SemiFuture
 
template<class >
class Future
 

Detailed Description

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

Definition at line 115 of file Future.h.

Member Typedef Documentation

template<class T >
using folly::futures::detail::FutureBase< T >::Core = futures::detail::Core<T>
protected

Definition at line 359 of file Future.h.

template<class T >
typedef T folly::futures::detail::FutureBase< T >::value_type

Definition at line 117 of file Future.h.

Constructor & Destructor Documentation

template<class T >
template<class T2 , typename >
folly::futures::detail::FutureBase< T >::FutureBase ( T2 &&  val)

Construct from a value (perfect forwarding)

Postconditions:

Definition at line 149 of file Future-inl.h.

150  : core_(Core::make(Try<T>(std::forward<T2>(val)))) {}
static Core * make()
State will be Start.
Definition: Core.h:205
template<class T >
template<typename T2 >
folly::futures::detail::FutureBase< T >::FutureBase ( typename std::enable_if< std::is_same< Unit, T2 >::value >::type )

Construct a (logical) FutureBase-of-void.

Postconditions:

Definition at line 154 of file Future-inl.h.

References testing::Args(), folly::T, type, and folly::futures::detail::FutureBase< T >::value().

156  : core_(Core::make(Try<T>(T()))) {}
folly::std T
static Core * make()
State will be Start.
Definition: Core.h:205
template<class T >
template<class... Args, typename std::enable_if< std::is_constructible< T, Args &&... >::value, int >::type >
folly::futures::detail::FutureBase< T >::FutureBase ( in_place_t  ,
Args &&...  args 
)
explicit

Definition at line 163 of file Future-inl.h.

164  : core_(Core::make(in_place, std::forward<Args>(args)...)) {}
in_place_tag in_place(in_place_tag={})
Definition: Utility.h:235
static Core * make()
State will be Start.
Definition: Core.h:205
template<class T >
folly::futures::detail::FutureBase< T >::FutureBase ( FutureBase< T > const &  )
delete
template<class T >
folly::futures::detail::FutureBase< T >::FutureBase ( SemiFuture< T > &&  other)
noexcept

Definition at line 138 of file Future-inl.h.

138  : core_(other.core_) {
139  other.core_ = nullptr;
140 }
template<class T >
folly::futures::detail::FutureBase< T >::FutureBase ( Future< T > &&  other)
noexcept

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

143  : core_(other.core_) {
144  other.core_ = nullptr;
145 }
template<class T >
folly::futures::detail::FutureBase< T >::FutureBase ( Future< T > const &  )
delete
template<class T >
folly::futures::detail::FutureBase< T >::FutureBase ( SemiFuture< T > const &  )
delete
template<class T >
folly::futures::detail::FutureBase< T >::~FutureBase ( )

Definition at line 173 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::detach().

173  {
174  detach();
175 }
template<class T >
folly::futures::detail::FutureBase< T >::FutureBase ( Core obj)
inlineexplicitprotected

Definition at line 401 of file Future.h.

References folly::pushmi::__adl::noexcept().

401 : core_(obj) {}
template<class T >
folly::futures::detail::FutureBase< T >::FutureBase ( futures::detail::EmptyConstruct  )
explicitprotectednoexcept

Definition at line 274 of file Future-inl.h.

275  : core_(nullptr) {}

Member Function Documentation

template<class T >
void folly::futures::detail::FutureBase< T >::assign ( FutureBase< T > &&  other)
protectednoexcept
template<class T >
void folly::futures::detail::FutureBase< T >::cancel ( )
inline

Raises a FutureCancellation interrupt. See raise(exception_wrapper) for details.

Definition at line 343 of file Future.h.

343  {
344  raise(FutureCancellation());
345  }
template<class T >
Core const& folly::futures::detail::FutureBase< T >::getCore ( ) const
inlineprotected

Definition at line 369 of file Future.h.

369  {
370  return getCoreImpl(*this);
371  }
static decltype(auto) getCoreImpl(Self &self)
Definition: Future.h:374
template<class T >
template<typename Self >
static decltype(auto) folly::futures::detail::FutureBase< T >::getCoreImpl ( Self &  self)
inlinestaticprotected

Definition at line 374 of file Future.h.

374  {
375  if (!self.core_) {
376  throw_exception<FutureInvalid>();
377  }
378  return *self.core_;
379  }
template<class T >
Try<T>& folly::futures::detail::FutureBase< T >::getCoreTryChecked ( )
inlineprotected

Definition at line 381 of file Future.h.

Referenced by folly::futures::detail::FutureBase< T >::result().

381  {
382  return getCoreTryChecked(*this);
383  }
template<class T >
Try<T> const& folly::futures::detail::FutureBase< T >::getCoreTryChecked ( ) const
inlineprotected

Definition at line 384 of file Future.h.

384  {
385  return getCoreTryChecked(*this);
386  }
template<class T >
template<typename Self >
static decltype(auto) folly::futures::detail::FutureBase< T >::getCoreTryChecked ( Self &  self)
inlinestaticprotected

Definition at line 389 of file Future.h.

389  {
390  auto& core = self.getCore();
391  if (!core.hasResult()) {
392  throw_exception<FutureNotReady>();
393  }
394  return core.getTry();
395  }
template<class T >
int8_t folly::futures::detail::FutureBase< T >::getPriority ( ) const
inline

Definition at line 348 of file Future.h.

348  {
349  return getCore().getPriority();
350  }
int8_t getPriority() const
Definition: Core.h:440
template<class T >
bool folly::futures::detail::FutureBase< T >::hasException ( ) const

True if the result is an exception (not a value) on a future for which isReady returns true.

Equivalent to result().hasException()

Preconditions:

Definition at line 228 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::result().

228  {
229  return result().hasException();
230 }
template<class T >
bool folly::futures::detail::FutureBase< T >::hasValue ( ) const

True if the result is a value (not an exception) on a future for which isReady returns true.

Equivalent to result().hasValue()

Preconditions:

Definition at line 223 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::result().

Referenced by fizz::server::test::ServerProtocolTest::getActions(), and folly::Future< T >::willEqual().

223  {
224  return result().hasValue();
225 }
template<class T >
bool folly::futures::detail::FutureBase< T >::isReady ( ) const

True when the result (or exception) is ready; see value(), result(), etc.

Preconditions:

Definition at line 218 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::getCore(), and folly::futures::detail::Core< T >::hasResult().

Referenced by folly::Future< T >::getTryVia(), folly::Future< T >::getVia(), folly::makePromiseContract(), TEST(), folly::futures::detail::waitViaImpl(), and folly::Future< T >::within().

218  {
219  return getCore().hasResult();
220 }
bool hasResult() const noexcept
Definition: Core.h:242
template<class T >
Optional< Try< T > > folly::futures::detail::FutureBase< T >::poll ( )

Returns either an Optional holding the result or an empty Optional depending on whether or not (respectively) the promise has been fulfilled (i.e., isReady() == true).

Preconditions:

Postconditions:

  • valid() == true (note however that this moves-out the result when it returns a populated Try<T>, which effects any subsequent use of that result, e.g., poll(), result(), value(), get(), etc.)

Definition at line 255 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::getCore(), and folly::gen::move.

255  {
256  auto& core = getCore();
257  return core.hasResult() ? Optional<Try<T>>(std::move(core.getTry()))
258  : Optional<Try<T>>();
259 }
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
folly::std T
template<class T >
void folly::futures::detail::FutureBase< T >::raise ( exception_wrapper  interrupt)

Provides a threadsafe back-channel so the consumer's thread can send an interrupt-object to the producer's thread.

If the promise-holder registers an interrupt-handler and consumer thread raises an interrupt early enough (details below), the promise-holder will typically halt its work, fulfilling the future with an exception or some special non-exception value.

However this interrupt request is voluntary, asynchronous, & advisory:

  • Voluntary: the producer will see the interrupt only if the producer uses a Promise object and registers an interrupt-handler; see Promise::setInterruptHandler().
  • Asynchronous: the producer will see the interrupt only if raise() is called before (or possibly shortly after) the producer is done producing its result, which is asynchronous with respect to the call to raise().
  • Advisory: the producer's interrupt-handler can do whatever it wants, including ignore the interrupt or perform some action other than halting its producer-work.

Guidelines:

  • It is ideal if the promise-holder can both halt its work and fulfill the promise early, typically with the same exception that was delivered to the promise-holder in the form of an interrupt.
  • If the promise-holder does not do this, and if it holds the promise alive for a long time, then the whole continuation chain will not be invoked and the whole future chain will be kept alive for that long time as well.
  • It is also ideal if the promise-holder can invalidate the promise.
  • The promise-holder must also track whether it has set a result in the interrupt handler so that it does not attempt to do so outside the interrupt handler, and must track whether it has set a result in its normal flow so that it does not attempt to do so in the interrupt handler, since setting a result twice is an error. Because the interrupt handler can be invoked in some other thread, this tracking may have to be done with some form of concurrency control.

Preconditions:

Postconditions:

  • has no visible effect if raise() was previously called on this or any other Future/SemiFuture that uses the same shared state as this.
  • has no visible effect if the producer never (either in the past or in the future) registers an interrupt-handler.
  • has no visible effect if the producer fulfills its promise (sets the result) before (or possibly also shortly after) receiving the interrupt.
  • otherwise the promise-holder's interrupt-handler is called, passing the exception (within an exception_wrapper).

The specific thread used to invoke the producer's interrupt-handler (if it is called at all) depends on timing:

  • if the interrupt-handler is registered prior to raise() (or possibly concurrently within the call to raise()), the interrupt-handler will be executed using this current thread within the call to raise().
  • if the interrupt-handler is registered after raise() (and possibly concurrently within the call to raise()), the interrupt-handler will be executed using the producer's thread within the call to Promise::setInterruptHandler().

Synchronizes between raise() (in the consumer's thread) and Promise::setInterruptHandler() (in the producer's thread).

Definition at line 262 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::getCore(), folly::gen::move, and folly::futures::detail::Core< T >::raise().

262  {
263  getCore().raise(std::move(exception));
264 }
void raise(exception_wrapper e)
Definition: Core.h:453
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
template<class T >
template<class E >
void folly::futures::detail::FutureBase< T >::raise ( E &&  exception)
inline

Raises the specified exception-interrupt. See raise(exception_wrapper) for details.

Definition at line 336 of file Future.h.

References type.

336  {
338  std::forward<E>(exception)));
339  }
PskType type
template<class T >
Try< T > && folly::futures::detail::FutureBase< T >::result ( )

Returns a reference to the result's Try if it is ready, with a reference category and const-qualification like those of the future.

Does not wait(); see get() for that.

Preconditions:

Postconditions:

  • This call does not mutate the future's result.
  • However calling code may mutate that result (including moving it out by move-constructing or move-assigning another result from it), for example, via the & or the && overloads or via casts.

Definition at line 198 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::getCoreTryChecked().

Referenced by folly::collect(), folly::collectN(), folly::Future< T >::getTry(), folly::Future< T >::getTryVia(), folly::futures::detail::FutureBase< T >::hasException(), folly::futures::detail::FutureBase< T >::hasValue(), folly::futures::detail::FutureBase< T >::result(), and folly::futures::detail::FutureBase< T >::value().

198  {
199  return getCoreTryChecked();
200 }
template<class T >
Try< T > const && folly::futures::detail::FutureBase< T >::result ( ) const
template<class T >
Try<T>&& folly::futures::detail::FutureBase< T >::result ( )
template<class T >
Try<T> const&& folly::futures::detail::FutureBase< T >::result ( ) const
template<class T >
template<class F >
void folly::futures::detail::FutureBase< T >::setCallback_ ( F &&  func)

This is not the method you're looking for.

This needs to be public because it's used by make* and when*, and it's not worth listing all those and their fancy template signatures as friends. But it's not for public consumption.

Definition at line 268 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::getCore(), folly::RequestContext::saveContext(), folly::futures::detail::Core< T >::setCallback(), and folly::futures::detail::FutureBase< T >::throwIfContinued().

Referenced by folly::futures::detail::chainExecutor(), folly::collectN(), folly::Future< T >::onError(), folly::Future< T >::onTimeout(), folly::futures::detail::FutureBase< T >::thenImplementation(), and folly::SemiFuture< T >::wait().

268  {
270  getCore().setCallback(std::forward<F>(func), RequestContext::saveContext());
271 }
static std::shared_ptr< RequestContext > saveContext()
Definition: Request.h:196
void setCallback(F &&func, std::shared_ptr< folly::RequestContext > context)
Definition: Core.h:306
template<class T >
template<class F >
void folly::futures::detail::FutureBase< T >::setCallback_ ( F &&  func,
std::shared_ptr< folly::RequestContext context 
)
template<class T >
void folly::futures::detail::FutureBase< T >::setExecutor ( Executor x,
int8_t  priority = Executor::MID_PRI 
)
inlineprotected

Definition at line 420 of file Future.h.

Referenced by folly::SemiFuture< T >::defer(), folly::SemiFuture< T >::operator=(), folly::SemiFuture< T >::SemiFuture(), and folly::Future< T >::via().

420  {
421  getCore().setExecutor(x, priority);
422  }
Definition: InvokeTest.cpp:58
void setExecutor(Executor::KeepAlive<> x, int8_t priority=Executor::MID_PRI)
Definition: Core.h:424
template<class T >
void folly::futures::detail::FutureBase< T >::setExecutor ( Executor::KeepAlive<>  x,
int8_t  priority = Executor::MID_PRI 
)
inlineprotected

Definition at line 424 of file Future.h.

References folly::futures::detail::convertFuture(), f, folly::futures::detail::getDeferredExecutor(), folly::gen::move, folly::futures::detail::stealDeferredExecutor(), and type.

426  {
427  getCore().setExecutor(std::move(x), priority);
428  }
Definition: InvokeTest.cpp:58
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
void setExecutor(Executor::KeepAlive<> x, int8_t priority=Executor::MID_PRI)
Definition: Core.h:424
template<class T >
template<typename F , typename R >
std::enable_if< R::ReturnsFuture::value, typename R::Return >::type folly::futures::detail::FutureBase< T >::thenImplementation ( F &&  func,
 
)
protected

Definition at line 311 of file Future-inl.h.

References B, folly::futures::detail::FutureBase< T >::core_, folly::Promise< T >::core_, f, folly::futures::detail::FutureBase< T >::getCore(), folly::futures::detail::FutureBase< T >::getExecutor(), folly::Promise< T >::getSemiFuture(), folly::futures::detail::detail_msvc_15_7_workaround::invoke(), folly::futures::detail::makeCoreCallbackState(), folly::makeTryWith(), folly::gen::move, folly::futures::detail::FutureBase< T >::setCallback_(), folly::pushmi::detail::t, and value.

Referenced by folly::futures::detail::chainExecutor(), folly::Future< T >::thenTry(), folly::Future< T >::thenValue(), folly::Future< T >::via(), and folly::futures::detail::FutureBase< T >::withinImplementation().

311  {
312  static_assert(
313  R::Arg::ArgsSize::value <= 1, "Then must take zero/one argument");
314  typedef typename R::ReturnsFuture::Inner B;
315 
316  Promise<B> p;
317  p.core_->setInterruptHandlerNoLock(this->getCore().getInterruptHandler());
318 
319  // grab the Future now before we lose our handle on the Promise
320  auto sf = p.getSemiFuture();
321  sf.setExecutor(this->getExecutor());
322  auto f = Future<B>(sf.core_);
323  sf.core_ = nullptr;
324 
325  /* This is a bit tricky.
326 
327  We can't just close over *this in case this Future gets moved. So we
328  make a new dummy Future. We could figure out something more
329  sophisticated that avoids making a new Future object when it can, as an
330  optimization. But this is correct.
331 
332  core_ can't be moved, it is explicitly disallowed (as is copying). But
333  if there's ever a reason to allow it, this is one place that makes that
334  assumption and would need to be fixed. We use a standard shared pointer
335  for core_ (by copying it in), which means in essence obj holds a shared
336  pointer to itself. But this shouldn't leak because Promise will not
337  outlive the continuation, because Promise will setException() with a
338  broken Promise if it is destructed before completed. We could use a
339  weak pointer but it would have to be converted to a shared pointer when
340  func is executed (because the Future returned by func may possibly
341  persist beyond the callback, if it gets moved), and so it is an
342  optimization to just make it shared from the get-go.
343 
344  Two subtle but important points about this design. futures::detail::Core
345  has no back pointers to Future or Promise, so if Future or Promise get
346  moved (and they will be moved in performant code) we don't have to do
347  anything fancy. And because we store the continuation in the
348  futures::detail::Core, not in the Future, we can execute the continuation
349  even after the Future has gone out of scope. This is an intentional design
350  decision. It is likely we will want to be able to cancel a continuation
351  in some circumstances, but I think it should be explicit not implicit
352  in the destruction of the Future used to create it.
353  */
354  this->setCallback_(
356  std::move(p), std::forward<F>(func))](Try<T>&& t) mutable {
357  if (!R::Arg::isTry() && t.hasException()) {
358  state.setException(std::move(t.exception()));
359  } else {
360  state.setTry(makeTryWith([&] {
362  }));
363  }
364  });
365  return f;
366 }
auto f
decltype(auto) invoke(R, State &state, Try< T > &)
Definition: Future-inl.h:285
Executor * getExecutor() const
Definition: Future.h:412
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
auto makeCoreCallbackState(Promise< T > &&p, F &&f) noexcept(noexcept(CoreCallbackState< T, F >(std::declval< Promise< T > && >(), std::declval< F && >())))
Definition: Future-inl.h:125
static const char *const value
Definition: Conv.cpp:50
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
state
Definition: http_parser.c:272
#define B(name, bit)
Definition: CpuId.h:178
template<class T >
template<typename F , typename R >
std::enable_if<R::ReturnsFuture::value, typename R::Return>::type folly::futures::detail::FutureBase< T >::thenImplementation ( F &&  func,
 
)
protected
template<class T >
void folly::futures::detail::FutureBase< T >::throwIfContinued ( ) const
protected

Definition at line 248 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::core_, and folly::futures::detail::Core< T >::hasCallback().

Referenced by folly::futures::detail::FutureBase< T >::setCallback_().

248  {
249  if (!core_ || core_->hasCallback()) {
250  throw_exception<FutureAlreadyContinued>();
251  }
252 }
bool hasCallback() const noexcept
May call from any thread.
Definition: Core.h:231
template<class T >
void folly::futures::detail::FutureBase< T >::throwIfInvalid ( ) const
protected

Definition at line 241 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::core_.

Referenced by folly::Future< T >::via().

241  {
242  if (!core_) {
243  throw_exception<FutureInvalid>();
244  }
245 }
template<class T >
bool folly::futures::detail::FutureBase< T >::valid ( ) const
inlinenoexcept

true if this has a shared state; false if this has been either moved-out or created without a shared state.

Definition at line 162 of file Future.h.

References context, folly::netops::poll(), and folly::value().

162  {
163  return core_ != nullptr;
164  }
template<class T >
T && folly::futures::detail::FutureBase< T >::value ( )

Returns a reference to the result value if it is ready, with a reference category and const-qualification like those of the future.

Does not wait(); see get() for that.

Preconditions:

Postconditions:

  • If an exception has been captured (i.e., if hasException() == true), throws that exception.
  • This call does not mutate the future's value.
  • However calling code may mutate that value (including moving it out by move-constructing or move-assigning another value from it), for example, via the & or the && overloads or via casts.

Definition at line 178 of file Future-inl.h.

References folly::futures::detail::FutureBase< T >::result().

Referenced by BENCHMARK_RELATIVE(), folly::collectN(), folly::Future< T >::Future(), folly::futures::detail::FutureBase< T >::FutureBase(), folly::Future< T >::getVia(), folly::makeFuture(), folly::makeFutureWith(), folly::makeSemiFuture(), folly::makeSemiFutureWith(), folly::Future< T >::onError(), folly::Future< T >::onTimeout(), folly::Future< T >::operator=(), folly::reduce(), TEST(), folly::futures::detail::FutureBase< T >::value(), and folly::futures::detail::waitImpl().

178  {
179  return result().value();
180 }
template<class T >
T const && folly::futures::detail::FutureBase< T >::value ( ) const
template<class T >
T&& folly::futures::detail::FutureBase< T >::value ( )
template<class T >
T const&& folly::futures::detail::FutureBase< T >::value ( ) const
template<class T >
template<typename E >
SemiFuture< T > folly::futures::detail::FutureBase< T >::withinImplementation ( Duration  dur,
E  e,
Timekeeper tk 
)
protected

Definition at line 430 of file Future-inl.h.

References f, folly::detail::getTimekeeperSingleton(), LIKELY, folly::gen::move, folly::pushmi::detail::t, folly::futures::detail::FutureBase< T >::thenImplementation(), folly::to_weak_ptr(), and UNLIKELY.

430  {
431  struct Context {
432  explicit Context(E ex) : exception(std::move(ex)) {}
433  E exception;
434  Future<Unit> thisFuture;
435  Promise<T> promise;
436  std::atomic<bool> token{false};
437  };
438 
439  std::shared_ptr<Timekeeper> tks;
440  if (LIKELY(!tk)) {
442  tk = tks.get();
443  }
444 
445  if (UNLIKELY(!tk)) {
446  return makeSemiFuture<T>(FutureNoTimekeeper());
447  }
448 
449  auto ctx = std::make_shared<Context>(std::move(e));
450 
451  auto f = [ctx](Try<T>&& t) {
452  if (!ctx->token.exchange(true, std::memory_order_relaxed)) {
453  ctx->promise.setTry(std::move(t));
454  }
455  };
456  using R = futures::detail::callableResult<T, decltype(f)>;
457  ctx->thisFuture = this->thenImplementation(std::move(f), R{});
458 
459  // Properly propagate interrupt values through futures chained after within()
460  ctx->promise.setInterruptHandler(
461  [weakCtx = to_weak_ptr(ctx)](const exception_wrapper& ex) {
462  if (auto lockedCtx = weakCtx.lock()) {
463  lockedCtx->thisFuture.raise(ex);
464  }
465  });
466 
467  // Have time keeper use a weak ptr to hold ctx,
468  // so that ctx can be deallocated as soon as the future job finished.
469  tk->after(dur).thenTry([weakCtx = to_weak_ptr(ctx)](Try<Unit>&& t) mutable {
470  auto lockedCtx = weakCtx.lock();
471  if (!lockedCtx) {
472  // ctx already released. "this" completed first, cancel "after"
473  return;
474  }
475  // "after" completed first, cancel "this"
476  lockedCtx->thisFuture.raise(FutureTimeout());
477  if (!lockedCtx->token.exchange(true, std::memory_order_relaxed)) {
478  if (t.hasException()) {
479  lockedCtx->promise.setException(std::move(t.exception()));
480  } else {
481  lockedCtx->promise.setException(std::move(lockedCtx->exception));
482  }
483  }
484  });
485 
486  return ctx->promise.getSemiFuture();
487 }
auto f
std::shared_ptr< Timekeeper > getTimekeeperSingleton()
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
#define LIKELY(x)
Definition: Likely.h:47
STL namespace.
std::weak_ptr< T > to_weak_ptr(const std::shared_ptr< T > &ptr)
Definition: Memory.h:346
std::enable_if<!R::ReturnsFuture::value, typename R::Return >::type thenImplementation(F &&func, R)
Definition: Future-inl.h:311
#define UNLIKELY(x)
Definition: Likely.h:48

Friends And Related Function Documentation

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

Definition at line 357 of file Future.h.

template<class T >
friend class Promise< T >
friend

Definition at line 353 of file Future.h.

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

Definition at line 355 of file Future.h.

Member Data Documentation


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