29 #ifndef FOLLY_FUTURE_USING_FIBER 30 #if FOLLY_MOBILE || defined(__APPLE__) 31 #define FOLLY_FUTURE_USING_FIBER 0 33 #define FOLLY_FUTURE_USING_FIBER 1 44 #if FOLLY_FUTURE_USING_FIBER 60 template <
typename T,
typename F>
68 assert(before_barrier());
73 if (that.before_barrier()) {
74 new (&func_)
DF(std::forward<F>(that.func_));
82 if (before_barrier()) {
87 template <
typename...
Args>
90 assert(before_barrier());
91 return std::forward<F>(func_)(std::forward<Args>(args)...);
94 template <
typename...
Args>
104 stealPromise().setException(
std::move(ew));
108 assert(before_barrier());
124 template <
typename T,
typename F>
128 std::declval<F&&>()))) {
132 template <
typename T,
typename R,
typename...
Args>
139 other.core_ =
nullptr;
144 other.core_ =
nullptr;
148 template <
class T2,
typename>
153 template <
typename T2>
161 typename std::enable_if<std::is_constructible<
T,
Args&&...>
::value,
int>
:: 224 return result().hasValue();
229 return result().hasException();
243 throw_exception<FutureInvalid>();
250 throw_exception<FutureAlreadyContinued>();
281 namespace detail_msvc_15_7_workaround {
282 template <
typename R, std::
size_t S>
283 using IfArgsSizeIs = std::enable_if_t<R::Arg::ArgsSize::value == S, int>;
284 template <
typename R,
typename State,
typename T, IfArgsSizeIs<R, 0> = 0>
286 return state.invoke();
288 template <
typename R,
typename State,
typename T, IfArgsSizeIs<R, 1> = 0>
290 using Arg0 =
typename R::Arg::ArgList::FirstArg;
291 return state.invoke(t.template
get<R::Arg::isTry(), Arg0>());
293 template <
typename R,
typename State,
typename T, IfArgsSizeIs<R, 0> = 0>
295 return state.tryInvoke();
297 template <
typename R,
typename State,
typename T, IfArgsSizeIs<R, 1> = 0>
299 using Arg0 =
typename R::Arg::ArgList::FirstArg;
300 return state.tryInvoke(t.template
get<R::Arg::isTry(), Arg0>());
309 template <
typename F,
typename R>
314 typedef typename R::ReturnsFuture::Inner
B;
317 p.
core_->setInterruptHandlerNoLock(this->
getCore().getInterruptHandler());
357 if (!R::Arg::isTry() &&
t.hasException()) {
386 template <
typename F,
typename R>
391 typedef typename R::ReturnsFuture::Inner
B;
394 p.
core_->setInterruptHandlerNoLock(this->
getCore().getInterruptHandler());
406 if (!R::Arg::isTry() &&
t.hasException()) {
412 if (tf2.hasException()) {
415 auto statePromise =
state.stealPromise();
417 statePromise.core_->getExecutor(), *
std::move(tf2));
428 template <
typename E>
432 explicit Context(
E ex) : exception(
std::move(ex)) {}
436 std::atomic<bool> token{
false};
439 std::shared_ptr<Timekeeper> tks;
449 auto ctx = std::make_shared<Context>(
std::move(e));
452 if (!ctx->token.exchange(
true, std::memory_order_relaxed)) {
460 ctx->promise.setInterruptHandler(
462 if (
auto lockedCtx = weakCtx.lock()) {
463 lockedCtx->thisFuture.raise(ex);
470 auto lockedCtx = weakCtx.lock();
477 if (!lockedCtx->token.exchange(
true, std::memory_order_relaxed)) {
478 if (
t.hasException()) {
479 lockedCtx->promise.setException(
std::move(
t.exception()));
481 lockedCtx->promise.setException(
std::move(lockedCtx->exception));
486 return ctx->promise.getSemiFuture();
500 auto state = state_.load(std::memory_order_acquire);
501 if (
state == State::DETACHED) {
504 if (
state == State::HAS_EXECUTOR) {
508 DCHECK(
state == State::EMPTY);
510 if (state_.compare_exchange_strong(
513 std::memory_order_release,
514 std::memory_order_acquire)) {
517 DCHECK(
state == State::DETACHED ||
state == State::HAS_EXECUTOR);
518 if (
state == State::DETACHED) {
526 if (nestedExecutors_) {
527 auto nestedExecutors =
std::exchange(nestedExecutors_,
nullptr);
528 for (
auto& nestedExecutor : *nestedExecutors) {
529 nestedExecutor->setExecutor(executor.
copy());
533 auto state = state_.load(std::memory_order_acquire);
534 if (
state == State::EMPTY &&
535 state_.compare_exchange_strong(
538 std::memory_order_release,
539 std::memory_order_acquire)) {
543 DCHECK(
state == State::HAS_FUNCTION);
544 state_.store(State::HAS_EXECUTOR, std::memory_order_release);
549 if (nestedExecutors_) {
550 auto nestedExecutors =
std::exchange(nestedExecutors_,
nullptr);
551 for (
auto& nestedExecutor : *nestedExecutors) {
552 nestedExecutor->detach();
555 auto state = state_.load(std::memory_order_acquire);
556 if (
state == State::EMPTY &&
557 state_.compare_exchange_strong(
560 std::memory_order_release,
561 std::memory_order_acquire)) {
565 DCHECK(
state == State::HAS_FUNCTION);
566 state_.store(State::DETACHED, std::memory_order_release);
572 DCHECK(!nestedExecutors_);
574 std::vector<folly::Executor::KeepAlive<DeferredExecutor>>>(
586 auto keepAliveCount =
587 keepAliveCount_.fetch_add(1, std::memory_order_relaxed);
588 DCHECK(keepAliveCount > 0);
593 auto keepAliveCount =
594 keepAliveCount_.fetch_sub(1, std::memory_order_acq_rel);
595 DCHECK(keepAliveCount > 0);
596 if (keepAliveCount == 1) {
601 enum class State { EMPTY, HAS_FUNCTION, HAS_EXECUTOR, DETACHED };
602 std::atomic<State> state_{State::EMPTY};
605 std::unique_ptr<std::vector<folly::Executor::KeepAlive<DeferredExecutor>>>
607 std::atomic<ssize_t> keepAliveCount_{1};
613 auto wQueue = queue_.wlock();
614 if (wQueue->detached) {
617 bool empty = wQueue->funcs.empty();
618 wQueue->funcs.push_back(
std::move(func));
627 auto funcs =
std::move(queue_.wlock()->funcs);
628 for (
auto& func : funcs) {
633 using Clock = std::chrono::steady_clock;
636 if (!baton_.try_wait_until(deadline)) {
640 auto funcs =
std::move(queue_.wlock()->funcs);
641 for (
auto& func : funcs) {
650 auto wQueue = queue_.wlock();
651 wQueue->detached =
true;
664 auto keepAliveCount =
665 keepAliveCount_.fetch_add(1, std::memory_order_relaxed);
666 DCHECK(keepAliveCount > 0);
671 auto keepAliveCount =
672 keepAliveCount_.fetch_sub(1, std::memory_order_acq_rel);
673 DCHECK(keepAliveCount > 0);
674 if (keepAliveCount == 1) {
681 bool detached{
false};
687 std::atomic<ssize_t> keepAliveCount_{1};
718 typename std::enable_if<
724 return std::forward<F>(func)();
725 }
catch (std::exception& e) {
726 return makeSemiFuture<InnerType>(
729 return makeSemiFuture<InnerType>(
737 typename std::enable_if<
742 return makeSemiFuture<LiftedResult>(
743 makeTryWith([&func]()
mutable {
return std::forward<F>(func)(); }));
756 template <
class T,
class E>
783 assert(dynamic_cast<DeferredExecutor*>(
executor) !=
nullptr);
793 assert(dynamic_cast<DeferredExecutor*>(
executor) !=
nullptr);
794 auto executorKeepAlive =
797 return executorKeepAlive;
808 assert(dynamic_cast<DeferredExecutor*>(
executor) !=
nullptr);
816 releaseDeferredExecutor(this->
core_);
834 releaseDeferredExecutor(this->
core_);
841 releaseDeferredExecutor(this->
core_);
855 throw_exception<FutureNoExecutor>();
859 deferredExecutor->setExecutor(
executor.copy());
863 this->
core_ =
nullptr;
880 template <
typename F>
884 if (!deferredExecutor) {
886 deferredExecutor = newDeferredExecutor.get();
890 auto sf =
Future<T>(this->
core_).thenTry(std::forward<F>(func)).semi();
891 this->
core_ =
nullptr;
899 template <
typename F>
902 return std::move(*this).defer([
f = std::forward<F>(func)](
904 return std::forward<F>(f)(
907 typename futures::detail::valueCallableResult<T, F>::FirstArg>());
912 template <
class ExceptionType,
class F>
915 [func = std::forward<F>(func)](
Try<T>&&
t)
mutable {
916 if (auto e = t.template tryGetExceptionObject<ExceptionType>()) {
917 return makeSemiFutureWith(
918 [&]() mutable { return std::forward<F>(func)(*e); });
920 return makeSemiFuture<T>(std::move(t));
929 [func = std::forward<F>(func)](
Try<T> t)
mutable {
930 if (t.hasException()) {
931 return makeSemiFutureWith([&]() mutable {
932 return std::forward<F>(func)(std::move(t.exception()));
935 return makeSemiFuture<T>(std::move(t));
940 template <
typename T>
968 typename std::enable_if<
980 typename std::enable_if<
983 !std::is_convertible<T2&&, T>::value,
992 typename std::enable_if<
1010 return internal_future;
1019 this->
core_ =
nullptr;
1051 template <
typename T>
1052 template <
typename R,
typename Caller,
typename...
Args>
1054 R (Caller::*func)(
Args...),
1055 Caller* instance) && {
1056 typedef typename std::remove_cv<
typename std::remove_reference<
1061 return (instance->*func)(t.template get<isTry<FirstArg>::value, Args>()...);
1066 template <
typename F>
1069 auto lambdaFunc = [
f = std::forward<F>(func)](
folly::Try<T>&&
t)
mutable {
1077 template <
typename F>
1080 auto lambdaFunc = [
f = std::forward<F>(func)](
folly::Try<T>&&
t)
mutable {
1081 return std::forward<F>(
f)(
1091 template <
class ExceptionType,
class F>
1098 .onError([func = std::forward<F>(func)](ExceptionType& ex)
mutable {
1099 return std::forward<F>(func)(ex);
1112 .onError([func = std::forward<F>(func)](
1114 return std::forward<F>(func)(
std::move(ex));
1121 return std::move(*this).thenValue([](
T&&) {});
1127 typename std::enable_if<
1132 typedef std::remove_reference_t<
1137 "Return type of onError callback must be T or Future<T>");
1146 if (
auto e =
t.template tryGetExceptionObject<Exn>()) {
1147 state.setTry(makeTryWith([&] { return state.invoke(*e); }));
1162 typename std::enable_if<
1170 "Return type of onError callback must be T or Future<T>");
1171 typedef std::remove_reference_t<
1181 if (
auto e =
t.template tryGetExceptionObject<Exn>()) {
1182 auto tf2 = state.tryInvoke(*e);
1183 if (tf2.hasException()) {
1184 state.setException(std::move(tf2.exception()));
1186 tf2->setCallback_([p = state.stealPromise()](Try<T>&& t3) mutable {
1187 p.setTry(std::move(t3));
1205 [funcw = std::forward<F>(func)](
Try<T>&&
t)
mutable {
1206 std::forward<F>(funcw)();
1207 return makeFuture(std::move(t));
1214 return std::move(*this).within(dur, tk).template thenError<FutureTimeout>(
1215 [funcw = std::forward<F>(func)](
auto const&)
mutable {
1216 return std::forward<F>(funcw)();
1222 typename std::enable_if<
1230 "Return type of onError callback must be T or Future<T>");
1239 if (tf2.hasException()) {
1242 tf2->setCallback_([p =
state.stealPromise()](
Try<T>&& t3)
mutable {
1260 typename std::enable_if<
1262 !futures::detail::Extract<F>::ReturnsFuture::value,
1268 "Return type of onError callback must be T or Future<T>");
1275 if (
t.hasException()) {
1289 template <
class Func>
1293 return via(
x).thenValue([
f = std::forward<Func>(func)](
auto&&)
mutable {
1294 return std::forward<Func>(
f)();
1298 template <
class Func>
1302 .thenValue([
f = std::forward<Func>(func)](
auto&&)
mutable {
1303 return std::forward<Func>(
f)();
1325 return std::forward<F>(func)();
1326 }
catch (std::exception& e) {
1327 return makeFuture<InnerType>(
1337 typename std::enable_if<
1342 return makeFuture<LiftedResult>(
1343 makeTryWith([&func]()
mutable {
return std::forward<F>(func)(); }));
1356 template <
class T,
class E>
1380 template <
typename V,
typename... Fs, std::size_t... Is>
1386 template <
typename V,
typename... Fs>
1391 foreach_(
_{},
static_cast<V&&
>(
v), static_cast<Fs&&>(fs)...);
1394 template <
typename T>
1399 template <
typename T>
1405 template <
typename T>
1410 template <
typename... Ts>
1414 auto foreach = [&](
auto& future) {
1420 [](...) {}(
foreach(ts)...);
1423 template <
class InputIterator>
1426 InputIterator
first,
1427 InputIterator last) {
1428 for (
auto it = first; it != last; ++it) {
1439 template <
typename... Fs>
1442 using Result = std::tuple<Try<typename remove_cvref_t<Fs>::value_type>...>;
1451 std::vector<folly::Executor::KeepAlive<futures::detail::DeferredExecutor>>
1455 auto ctx = std::make_shared<Context>();
1457 [&](
auto i,
auto&&
f) {
1458 f.setCallback_([
i, ctx](
auto&&
t) {
1462 static_cast<Fs&&
>(fs)...);
1464 auto future = ctx->p.getSemiFuture();
1465 if (!executors.empty()) {
1471 deferredExecutor->setNestedExecutors(
std::move(executors));
1476 template <
typename... Fs>
1484 template <
class InputIterator>
1488 using F =
typename std::iterator_traits<InputIterator>::value_type;
1489 using T =
typename F::value_type;
1492 explicit Context(
size_t n) : results(n) {}
1497 std::vector<Try<T>> results;
1500 std::vector<folly::Executor::KeepAlive<futures::detail::DeferredExecutor>>
1504 auto ctx = std::make_shared<Context>(size_t(std::distance(first, last)));
1506 for (
size_t i = 0; first != last; ++
first, ++
i) {
1507 first->setCallback_(
1511 auto future = ctx->p.getSemiFuture();
1512 if (!executors.empty()) {
1518 deferredExecutor->setNestedExecutors(
std::move(executors));
1523 template <
class InputIterator>
1533 template <
class InputIterator>
1535 typename std::iterator_traits<InputIterator>::value_type::value_type>>
1537 using F =
typename std::iterator_traits<InputIterator>::value_type;
1538 using T =
typename F::value_type;
1541 explicit Context(
size_t n) :
result(n) {
1542 finalResult.reserve(n);
1545 if (!threw.load(std::memory_order_relaxed)) {
1550 std::back_inserter(finalResult),
1556 std::vector<Optional<T>>
result;
1557 std::vector<T> finalResult;
1558 std::atomic<bool> threw{
false};
1561 auto ctx = std::make_shared<Context>(std::distance(first, last));
1562 for (
size_t i = 0; first != last; ++
first, ++
i) {
1563 first->setCallback_([
i, ctx](
Try<T>&&
t) {
1564 if (
t.hasException()) {
1565 if (!ctx->threw.exchange(
true, std::memory_order_relaxed)) {
1566 ctx->p.setException(
std::move(
t.exception()));
1568 }
else if (!ctx->threw.load(std::memory_order_relaxed)) {
1579 template <
typename... Fs>
1582 using Result = std::tuple<typename remove_cvref_t<Fs>::value_type...>;
1585 if (!threw.load(std::memory_order_relaxed)) {
1590 std::tuple<Try<typename remove_cvref_t<Fs>::value_type>...> results;
1591 std::atomic<bool> threw{
false};
1594 auto ctx = std::make_shared<Context>();
1596 [&](
auto i,
auto&&
f) {
1597 f.setCallback_([
i, ctx](
auto&&
t) {
1598 if (
t.hasException()) {
1599 if (!ctx->threw.exchange(
true, std::memory_order_relaxed)) {
1600 ctx->p.setException(
std::move(
t.exception()));
1602 }
else if (!ctx->threw.load(std::memory_order_relaxed)) {
1607 static_cast<Fs&&
>(fs)...);
1614 template <
class InputIterator>
1619 using F =
typename std::iterator_traits<InputIterator>::value_type;
1620 using T =
typename F::value_type;
1624 std::atomic<bool> done{
false};
1627 auto ctx = std::make_shared<Context>();
1628 for (
size_t i = 0; first != last; ++
first, ++
i) {
1629 first->setCallback_([
i, ctx](
Try<T>&&
t) {
1630 if (!ctx->done.exchange(
true, std::memory_order_relaxed)) {
1640 template <
class InputIterator>
1643 typename std::iterator_traits<InputIterator>::value_type::value_type>>
1645 using F =
typename std::iterator_traits<InputIterator>::value_type;
1646 using T =
typename F::value_type;
1649 Context(
size_t n) : nTotal(n) {}
1651 std::atomic<bool> done{
false};
1652 std::atomic<size_t> nFulfilled{0};
1656 std::vector<folly::Executor::KeepAlive<futures::detail::DeferredExecutor>>
1660 auto ctx = std::make_shared<Context>(size_t(std::distance(first, last)));
1661 for (
size_t i = 0; first != last; ++
first, ++
i) {
1662 first->setCallback_([
i, ctx](
Try<T>&&
t) {
1663 if (!
t.hasException() &&
1664 !ctx->done.exchange(
true, std::memory_order_relaxed)) {
1665 ctx->p.setValue(std::make_pair(
i,
std::move(
t.value())));
1667 ctx->nFulfilled.fetch_add(1, std::memory_order_relaxed) + 1 ==
1669 ctx->p.setException(
t.exception());
1674 auto future = ctx->p.getSemiFuture();
1675 if (!executors.empty()) {
1681 deferredExecutor->setNestedExecutors(
std::move(executors));
1688 template <
class InputIterator>
1693 using F =
typename std::iterator_traits<InputIterator>::value_type;
1694 using T =
typename F::value_type;
1695 using Result = std::vector<std::pair<size_t, Try<T>>>;
1698 explicit Context(
size_t numFutures,
size_t min_)
1699 :
v(numFutures),
min(min_) {}
1701 std::vector<Optional<Try<T>>>
v;
1703 std::atomic<size_t> completed = {0};
1704 std::atomic<size_t> stored = {0};
1709 assert(std::distance(first, last) >= 0);
1711 if (
size_t(std::distance(first, last)) < n) {
1719 auto ctx = std::make_shared<Context>(size_t(std::distance(first, last)), n);
1720 for (
size_t i = 0; first != last; ++
first, ++
i) {
1723 auto const c = 1 + ctx->completed.fetch_add(1, std::memory_order_relaxed);
1731 auto const s = 1 + ctx->stored.fetch_add(1, std::memory_order_acq_rel);
1736 result.reserve(ctx->completed.load());
1737 for (
size_t j = 0; j < ctx->v.size(); ++j) {
1738 auto& entry = ctx->v[j];
1739 if (entry.hasValue()) {
1747 return ctx->p.getSemiFuture();
1752 template <
class It,
class T,
class F>
1754 if (first == last) {
1758 typedef typename std::iterator_traits<It>::value_type::value_type ItT;
1759 typedef typename std::
1764 auto sfunc = std::make_shared<std::decay_t<F>>(std::forward<F>(func));
1767 [initial = std::forward<T>(initial), sfunc](Try<ItT>&& head)
mutable {
1769 std::move(initial), head.template get<IsTry::value, Arg&&>());
1772 for (++first; first != last; ++
first) {
1774 [sfunc](std::tuple<
Try<T>, Try<ItT>>&&
t) {
1779 std::get<1>(
t).
template get<IsTry::value, Arg&&>());
1788 template <
class Collection,
class F,
class ItT,
class Result>
1789 std::vector<Future<Result>>
window(Collection input, F func,
size_t n) {
1797 -> std::vector<invoke_result_t<F, size_t>> {
1801 template <
class Collection,
class F,
class ItT,
class Result>
1802 std::vector<Future<Result>>
1808 template <
class Collection,
class F,
class ItT,
class Result>
1809 std::vector<Future<Result>>
1811 struct WindowContext {
1814 Collection&& input_,
1818 promises(input.size()),
1820 std::atomic<size_t>
i{0};
1823 std::vector<Promise<Result>> promises;
1826 static void spawn(std::shared_ptr<WindowContext> ctx) {
1827 size_t i = ctx->i.fetch_add(1, std::memory_order_relaxed);
1828 if (i < ctx->input.size()) {
1830 [&] {
return ctx->func(
std::move(ctx->input[i])); })
1831 .
via(ctx->executor.get());
1844 auto ctx = std::make_shared<WindowContext>(
1848 for (
size_t i = 0;
i <
max; ++
i) {
1849 executor->add([ctx]()
mutable { WindowContext::spawn(
std::move(ctx)); });
1852 std::vector<Future<Result>>
futures;
1853 futures.reserve(ctx->promises.size());
1854 for (
auto& promise : ctx->promises) {
1855 futures.emplace_back(promise.getSemiFuture().via(executor.
copy()));
1864 template <
class I,
class F>
1867 [minitial = std::forward<I>(initial),
1868 mfunc = std::forward<F>(func)](
T&& vals)
mutable {
1869 auto ret = std::move(minitial);
1870 for (auto& val : vals) {
1871 ret = mfunc(std::move(ret), std::move(val));
1880 template <
class It,
class T,
class F>
1882 using ItF =
typename std::iterator_traits<It>::value_type;
1883 using ItT =
typename ItF::value_type;
1886 if (first == last) {
1893 Context(
T&& memo, F&& fn,
size_t n)
1919 auto ctx = std::make_shared<Context>(
1921 for (
size_t i = 0; first != last; ++
first, ++
i) {
1934 if (++ctx->numThens_ == ctx->numFutures_) {
1936 ctx->memo_.setCallback_(
1948 mt.template get<IsTry::value, Arg&&>()));
1949 }
catch (std::exception& e) {
1979 .withinImplementation(dur, e, tk)
1991 return makeFuture<T>(std::get<0>(
std::move(tup)));
1997 return std::move(*this).semi().delayed(dur, tk).toUnsafeFuture();
2003 template <
class FutureType,
typename T =
typename FutureType::value_type>
2015 auto baton = std::make_shared<FutureBatonType>();
2022 assert(f.isReady());
2037 template <
class FutureType,
typename T =
typename FutureType::value_type>
2049 auto baton = std::make_shared<FutureBatonType>();
2055 if (baton->try_wait_for(dur)) {
2056 assert(f.isReady());
2076 template <
class T,
typename Rep,
typename Period>
2080 const std::chrono::duration<Rep, Period>& timeout) {
2091 auto deadline =
now + timeout;
2115 deferredExecutor->setExecutor(waitExecutor.copy());
2116 while (!ret.isReady()) {
2117 waitExecutor->drive();
2119 waitExecutor->detach();
2144 deferredExecutor->setExecutor(waitExecutor.copy());
2145 while (!ret.isReady()) {
2146 if (!waitExecutor->driveUntil(deadline)) {
2150 waitExecutor->detach();
2163 return future.isReady();
2168 return std::move(*this).getTry().value();
2173 return std::move(*this).getTry(dur).value();
2180 this->
core_ =
nullptr;
2188 this->
core_ =
nullptr;
2190 if (!future.isReady()) {
2191 throw_exception<FutureTimeout>();
2254 if (!future.isReady()) {
2255 throw_exception<FutureTimeout>();
2274 throw_exception<FutureTimeout>();
2288 throw_exception<FutureTimeout>();
2310 std::get<0>(
t), std::get<1>(
t));
2320 return std::move(*this).thenValue([p = std::forward<F>(predicate)](
T val) {
2321 T const& valConstRef = val;
2322 if (!p(valConstRef)) {
2323 throw_exception<FuturePredicateDoesNotObtain>();
2331 return p ? std::forward<F>(thunk)().unit() :
makeFuture();
2334 template <
class P,
class F>
2337 auto future = thunk();
2339 [predicate = std::forward<P>(predicate),
2340 thunk = std::forward<F>(thunk)](
auto&&)
mutable {
2341 return whileDo(std::forward<P>(predicate), std::forward<F>(thunk));
2351 return count->fetch_add(1, std::memory_order_relaxed) < n;
2353 std::forward<F>(thunk));
2357 template <
class It,
class F,
class ItT,
class Result>
2358 std::vector<Future<Result>>
map(It
first, It last, F func) {
2359 std::vector<Future<Result>> results;
2360 results.reserve(std::distance(first, last));
2361 for (
auto it = first; it != last; it++) {
2364 results.push_back(
std::move(*it).then(func));
2370 template <
class It,
class F,
class ItT,
class Result>
2372 std::vector<Future<Result>> results;
2373 results.reserve(std::distance(first, last));
2374 for (
auto it = first; it != last; it++) {
2377 results.push_back(
std::move(*it).via(&exec).then(func));
2385 template <
class Clock>
2393 return after(std::chrono::duration_cast<Duration>(when -
now));
folly::fibers::Baton FutureBatonType
void setException(exception_wrapper &&ew)
Future< T > via(Executor *executor, int8_t priority=Executor::MID_PRI)&&
Future & operator=(Future< T2 > &&)
Future< T > within(Duration dur, Timekeeper *tk=nullptr)&&
make_index_sequence< sizeof...(T)> index_sequence_for
void raise(exception_wrapper e)
void waitImpl(FutureType &f)
#define FOLLY_GNU_DISABLE_WARNING(warningName)
Future< T > thenError(F &&func)&&
#define FOLLY_POP_WARNING
bool try_drive_until(const std::chrono::time_point< Clock, Duration > &deadline) noexcept
decltype(auto) invoke(R, State &state, Try< T > &)
friend Future< T2 > makeFuture(Try< T2 >)
Future< Unit > whileDo(P &&predicate, F &&thunk)
static SemiFuture< T > makeEmpty()
typename invoke_result< F, Args... >::type invoke_result_t
std::shared_ptr< Timekeeper > getTimekeeperSingleton()
#define FOLLY_PUSH_WARNING
#define FOLLY_ALWAYS_INLINE
friend Future< Unit > when(bool p, F &&thunk)
CoreCallbackState(CoreCallbackState &&that) noexcept(noexcept(DF(std::declval< F && >())))
static Promise< T > makeEmpty() noexcept
Future< I > reduce(I &&initial, F &&func)&&
CoreCallbackState(Promise< T > &&promise, F &&func) noexcept(noexcept(DF(std::declval< F && >())))
Future< Unit > sleep(Duration dur, Timekeeper *tk)
void setExecutor(folly::Executor::KeepAlive<> executor)
Executor * getExecutor() const
std::vector< Func > funcs
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
static void releaseDeferredExecutor(Core *core)
static KeepAlive< DeferredExecutor > create()
void add(Func func) override
std::lock_guard< MicroSpinLock > MSLGuard
std::integral_constant< std::size_t, I > index_constant
auto makeCoreCallbackState(Promise< T > &&p, F &&f) noexcept(noexcept(CoreCallbackState< T, F >(std::declval< Promise< T > && >(), std::declval< F && >())))
std::vector< size_t >::iterator iterator
Future< T > unorderedReduce(It first, It last, T initial, F func)
SemiFuture< std::tuple< Try< typename remove_cvref_t< Fs >::value_type >... > > collectAllSemiFuture(Fs &&...fs)
internal::ArgsMatcher< InnerMatcher > Args(const InnerMatcher &matcher)
exception_wrapper & exception()&
—— Concurrent Priority Queue Implementation ——
std::unique_ptr< std::vector< folly::Executor::KeepAlive< DeferredExecutor > > > nestedExecutors_
in_place_tag in_place(in_place_tag={})
WindowFakeVector(size_t size)
requires E e noexcept(noexcept(s.error(std::move(e))))
in_place_tag(&)(in_place_tag) in_place_t
PUSHMI_INLINE_VAR constexpr detail::transform_fn transform
void setNestedExecutors(std::vector< folly::Executor::KeepAlive< DeferredExecutor >> executors)
SemiFuture< std::vector< std::pair< size_t, Try< typename std::iterator_traits< InputIterator >::value_type::value_type > > > > collectN(InputIterator first, InputIterator last, size_t n)
Try< T > & getTryVia(DrivableExecutor *e)
friend Future< Unit > times(int n, F &&thunk)
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
void keepAliveRelease() override
void setTry(Try< T > &&t)
typename lift_unit< T >::type Inner
Future< T > via(Executor *executor, int8_t priority=Executor::MID_PRI)&&
Returns a Future which will call back on the other side of executor.
void detachFuture() noexcept
std::vector< Future< Result > > window(Collection input, F func, size_t n)
Future< bool > willEqual(Future< T > &)
DeferredExecutor * getDeferredExecutor(SemiFuture< T > &future)
SemiFuture< std::pair< size_t, typename std::iterator_traits< InputIterator >::value_type::value_type > > collectAnyWithoutException(InputIterator first, InputIterator last)
std::enable_if< isFutureOrSemiFuture< invoke_result_t< F > >::value, SemiFuture< typename invoke_result_t< F >::value_type > >::type makeSemiFutureWith(F &&func)
Future< T > onTimeout(Duration, F &&func, Timekeeper *=nullptr)&&
constexpr std::decay< T >::type copy(T &&value) noexcept(noexcept(typename std::decay< T >::type(std::forward< T >(value))))
constexpr auto size(C const &c) -> decltype(c.size())
void raise(exception_wrapper interrupt)
bool hasException() const
std::enable_if_t< R::Arg::ArgsSize::value==S, int > IfArgsSizeIs
void setCallback_(F &&func)
static std::shared_ptr< RequestContext > saveContext()
std::weak_ptr< T > to_weak_ptr(const std::shared_ptr< T > &ptr)
std::chrono::milliseconds Duration
State
See Core for details.
constexpr auto empty(C const &c) -> decltype(c.empty())
void waitViaImpl(Future< T > &f, TimedDrivableExecutor *e, const std::chrono::duration< Rep, Period > &timeout)
typename lift_unit< T >::type lift_unit_t
Future< T > delayed(Duration, Timekeeper *=nullptr)&&
constexpr auto invoke(F &&f, Args &&...args) noexcept(noexcept(static_cast< F && >(f)(static_cast< Args && >(args)...))) -> decltype(static_cast< F && >(f)(static_cast< Args && >(args)...))
Future< T > filter(F &&predicate)&&
Future< typename futures::detail::tryCallableResult< T, F >::value_type > thenTry(F &&func)&&
PolymorphicAction< internal::InvokeAction< FunctionImpl > > Invoke(FunctionImpl function_impl)
SemiFuture< T > deferError(F &&func)&&
DeferredExecutor * getDeferredExecutor() const
Arg::ArgList::FirstArg FirstArg
Future< std::pair< size_t, Try< typename std::iterator_traits< InputIterator >::value_type::value_type > > > collectAny(InputIterator first, InputIterator last)
SemiFuture< T > & wait()&
void setTry(Try< T > &&t)
Try< T > & getCoreTryChecked()
std::enable_if<!R::ReturnsFuture::value, typename R::Return >::type thenImplementation(F &&func, R)
Future< T > & waitVia(DrivableExecutor *e)&
SemiFuture< T > delayed(Duration dur, Timekeeper *tk=nullptr)&&
void waitImpl(FutureType &f, Duration dur)
FOLLY_ATTR_VISIBILITY_HIDDEN static FOLLY_ALWAYS_INLINE InlineExecutor & instance() noexcept
auto lock(Synchronized< D, M > &synchronized, Args &&...args)
void convertFuture(SemiFuture< T > &&sf, SemiFuture< T > &f)
auto invoke(Args &&...args) noexcept(noexcept(std::declval< F && >()(std::declval< Args && >()...)))
Future< T > delayedUnsafe(Duration, Timekeeper *=nullptr)
Future< std::tuple< Try< typename remove_cvref_t< Fs >::value_type >... > > collectAll(Fs &&...fs)
SemiFuture< typename futures::detail::tryCallableResult< T, F >::value_type > defer(F &&func)&&
Future< T > chainExecutor(Executor *, Future< T > &&f)
bool before_barrier() const noexcept
bool driveUntil(Clock::time_point deadline)
void keepAliveRelease() override
static bool equals(const Try< T > &t1, const Try< T > &t2)
bool hasCallback() const noexcept
May call from any thread.
friend Future< Unit > whileDo(P &&predicate, F &&thunk)
void setExecutor(Executor::KeepAlive<> x, int8_t priority=Executor::MID_PRI)
static const char *const value
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
std::enable_if< isFuture< F >::value, Future< typename isFuture< T >::Inner > >::type unwrap()&&
void waitViaImpl(Future< T > &f, DrivableExecutor *e)
SemiFuture< typename futures::detail::valueCallableResult< T, F >::value_type > deferValue(F &&func)&&
void assign(FutureBase< T > &&other) noexcept
folly::Executor::KeepAlive executor_
std::chrono::steady_clock Clock
Executor * getExecutor() const
SemiFuture< T > getSemiFuture()
Future< std::vector< typename std::iterator_traits< InputIterator >::value_type::value_type > > collect(InputIterator first, InputIterator last)
void setExecutor(Executor *x, int8_t priority=Executor::MID_PRI)
folly::Executor::KeepAlive< DeferredExecutor > stealDeferredExecutor() const
T exchange(T &obj, U &&new_value)
std::enable_if< !std::is_same< invoke_result_t< F >, void >::value, Try< invoke_result_t< F > > >::type makeTryWith(F &&f)
SemiFuture< T > withinImplementation(Duration dur, E e, Timekeeper *tk)&&
typename std::conditional< is_invocable< F, T &&, Try< ItT > && >::value, Try< ItT >, ItT >::type MaybeTryArg
void stealDeferredExecutors(std::vector< folly::Executor::KeepAlive< DeferredExecutor >> &executors, InputIterator first, InputIterator last)
Future< T > toUnsafeFuture()&&
bool keepAliveAcquire() override
void setInterruptHandlerNoLock(std::function< void(exception_wrapper const &)> fn)
void setCallback(F &&func, std::shared_ptr< folly::RequestContext > context)
void throwIfInvalid() const
Future< Unit > at(std::chrono::time_point< Clock > when)
const internal::AnythingMatcher _
void throwIfContinued() const
Executor::KeepAlive< ExecutorT > getKeepAliveToken(ExecutorT *executor)
bool keepAliveAcquire() override
T getVia(DrivableExecutor *e)
folly::Synchronized< Queue > queue_
Future< T > ensure(F &&func)&&
FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN void foreach(V &&v, Fs &&...fs)
#define FOLLY_ATTR_VISIBILITY_HIDDEN
std::enable_if< !is_invocable< F, exception_wrapper >::value &&!futures::detail::Extract< F >::ReturnsFuture::value, Future< T > >::type onError(F &&func)&&
PUSHMI_INLINE_VAR constexpr detail::get_fn< T > get
FOLLY_ALWAYS_INLINE FOLLY_ATTR_VISIBILITY_HIDDEN void foreach_(index_sequence< Is... >, V &&v, Fs &&...fs)
decltype(auto) tryInvoke(R, State &state, Try< T > &)
void add(Func func) override
Future< typename futures::detail::valueCallableResult< T, F >::value_type > thenValue(F &&func)&&
void stealDeferredExecutorsVariadic(std::vector< folly::Executor::KeepAlive< DeferredExecutor >> &executors, Ts &...ts)
bool hasResult() const noexcept
folly::Executor::KeepAlive< DeferredExecutor > stealDeferredExecutor(Future< T > &)
auto unwrapTryTuple(Tuple &&instance)
auto tryInvoke(Args &&...args) noexcept
static KeepAlive< WaitExecutor > create()
Optional< Try< T > > poll()
Promise< T > stealPromise() noexcept
size_t operator[](const size_t index) const
std::enable_if< isFuture< invoke_result_t< F > >::value, invoke_result_t< F > >::type makeFutureWith(F &&func)
static Future< T > makeEmpty()
SemiFuture< typename std::decay< T >::type > makeSemiFuture(T &&t)
SemiFuture & operator=(SemiFuture const &)=delete
constexpr detail::First first
static Core * make()
State will be Start.
bool hasException() const