36#include <seastar/core/task.hh>
37#include <seastar/core/thread_impl.hh>
38#include <seastar/core/function_traits.hh>
40#include <seastar/util/critical_alloc_section.hh>
41#include <seastar/util/noncopyable_function.hh>
42#include <seastar/util/backtrace.hh>
43#include <seastar/util/std-compat.hh>
44#include <seastar/util/modules.hh>
49 std::exception_ptr inner;
50 std::exception_ptr outer;
51 nested_exception(std::exception_ptr inner, std::exception_ptr outer)
noexcept;
54 [[noreturn]]
void rethrow_nested()
const;
55 virtual const char* what()
const noexcept override;
148SEASTAR_MODULE_EXPORT_BEGIN
149template <
class T =
void>
155template <
typename... T>
166template <
typename T = void,
typename... A>
174 return make_ready_future<std::remove_cv_t<std::remove_reference_t<T>>>(
184template <
typename T =
void>
187template <
typename T =
void,
typename Exception>
190template <
typename T =
void>
192 return make_exception_future<T>(std::exception_ptr(ex));
195template <
typename T =
void>
197 return make_exception_future<T>(
static_cast<const std::exception_ptr&
>(ex));
200template <
typename T =
void>
203 return make_exception_future<T>(std::exception_ptr(ex));
205SEASTAR_MODULE_EXPORT_END
207void engine_exit(std::exception_ptr eptr = {});
209void report_failed_future(
const std::exception_ptr& ex)
noexcept;
211void report_failed_future(
const future_state_base& state)
noexcept;
232template <
typename T =
void>
240template <
class T =
void>
241class promise_base_with_type;
246template <
typename... T>
247struct future_stored_type;
250struct future_stored_type<> {
251 using type = monostate;
255struct future_stored_type<T> {
256 using type = std::conditional_t<std::is_void_v<T>, internal::monostate, T>;
259template <
typename... T>
260using future_stored_type_t =
typename future_stored_type<T...>::type;
263using future_tuple_type_t = std::conditional_t<std::is_same_v<T, monostate>, std::tuple<>, std::tuple<T>>;
268struct get0_return_type;
271struct get0_return_type<internal::monostate> {
273 static type get0(internal::monostate) { }
277struct get0_return_type {
279 static T get0(T&& v) {
return std::move(v); }
283using maybe_wrap_ref = std::conditional_t<std::is_reference_v<T>, std::reference_wrapper<std::remove_reference_t<T>>, T>;
291struct uninitialized_wrapper {
292 using tuple_type = future_tuple_type_t<T>;
293 [[no_unique_address]]
union any {
297 [[no_unique_address]] maybe_wrap_ref<T> value;
301 uninitialized_wrapper() noexcept = default;
302 template<typename... U>
303 std::enable_if_t<!
std::is_same_v<
std::tuple<
std::remove_cv_t<U>...>,
std::tuple<tuple_type>>,
void>
304 uninitialized_set(U&&... vs) {
305 new (&_v.value) maybe_wrap_ref<T>(T(std::forward<U>(vs)...));
307 void uninitialized_set(tuple_type&& v) {
308 uninitialized_set(std::move(std::get<0>(v)));
310 void uninitialized_set(
const tuple_type& v) {
311 uninitialized_set(std::get<0>(v));
313 maybe_wrap_ref<T>& uninitialized_get() {
316 const maybe_wrap_ref<T>& uninitialized_get()
const {
322struct uninitialized_wrapper<internal::monostate> {
323 [[no_unique_address]] internal::monostate _v;
325 uninitialized_wrapper() noexcept = default;
326 void uninitialized_set() {
328 void uninitialized_set(internal::monostate) {
330 void uninitialized_set(std::tuple<>&& v) {
332 void uninitialized_set(
const std::tuple<>& v) {
334 internal::monostate& uninitialized_get() {
337 const internal::monostate& uninitialized_get()
const {
343struct is_trivially_move_constructible_and_destructible {
344 static constexpr bool value = std::is_trivially_move_constructible_v<T> && std::is_trivially_destructible_v<T>;
348struct all_true : std::false_type {};
351struct all_true<> : std::true_type {};
354struct all_true<true, v...> :
public all_true<v...> {};
357struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper;
359template <
typename... T>
360struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper<
std::tuple<T...>> {
361 static constexpr bool value = all_true<is_trivially_move_constructible_and_destructible<T>::value...>::value;
365static constexpr bool is_tuple_effectively_trivially_move_constructible_and_destructible =
366 is_tuple_effectively_trivially_move_constructible_and_destructible_helper<T>::value;
399 static_assert(
sizeof(std::exception_ptr) ==
sizeof(
void*),
"exception_ptr not a pointer");
400 enum class state : uintptr_t {
410 result_unavailable = 2,
415 any()
noexcept { st = state::future; }
416 any(state s)
noexcept { st = s; }
417 void set_exception(std::exception_ptr&& e)
noexcept {
418 new (&ex) std::exception_ptr(std::move(e));
419 assert(st >= state::exception_min);
421 any(std::exception_ptr&& e)
noexcept {
422 set_exception(std::move(e));
425 bool valid()
const noexcept {
return st != state::invalid && st != state::result_unavailable; }
426 bool available()
const noexcept {
return st == state::result || st >= state::exception_min; }
427 bool failed()
const noexcept {
return __builtin_expect(st >= state::exception_min,
false); }
428 void check_failure()
noexcept;
430 std::exception_ptr take_exception()
noexcept {
431 std::exception_ptr ret(std::move(ex));
444 void move_it(
any&& x)
noexcept {
453 memmove(
static_cast<void*
>(
this), &x,
sizeof(
any));
454 x.st = state::invalid;
456 if (x.st < state::exception_min) {
458 x.st = state::invalid;
460 new (&ex) std::exception_ptr(x.take_exception());
465 move_it(std::move(x));
467 any& operator=(
any&& x)
noexcept {
472 move_it(std::move(x));
475 bool has_result()
const noexcept {
476 return st == state::result || st == state::result_unavailable;
479 std::exception_ptr ex;
485 future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
497 void rethrow_exception() &&;
498 void rethrow_exception() const&;
502 bool valid() const noexcept {
return _u.valid(); }
503 bool available() const noexcept {
return _u.available(); }
504 bool failed() const noexcept {
return _u.failed(); }
506 void ignore() noexcept;
508 void set_exception(
std::exception_ptr&& ex) noexcept {
509 assert(_u.st == state::future);
510 _u.set_exception(std::move(ex));
512 future_state_base& operator=(future_state_base&& x)
noexcept =
default;
513 void set_exception(future_state_base&& state)
noexcept {
514 assert(_u.st == state::future);
515 *
this = std::move(state);
517 std::exception_ptr get_exception() &&
noexcept {
518 assert(_u.st >= state::exception_min);
520 return _u.take_exception();
522 const std::exception_ptr& get_exception() const& noexcept {
523 assert(_u.st >= state::exception_min);
526 template <
typename U>
527 friend struct future_state;
528 template <
typename U>
530 template <typename U>
532 template <typename T>
540 report_failed_future(std::move(*
this));
550struct future_state :
public future_state_base,
private internal::uninitialized_wrapper<T> {
551 static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible_v<T>;
552 static constexpr bool has_trivial_move_and_destroy = internal::is_trivially_move_constructible_and_destructible<T>::value;
553 static_assert(std::is_nothrow_move_constructible_v<T>,
554 "Types must be no-throw move constructible");
555 static_assert(std::is_nothrow_destructible_v<T>,
556 "Types must be no-throw destructible");
557 future_state() noexcept = default;
558 void move_it(future_state&& x) noexcept {
559 if constexpr (has_trivial_move_and_destroy) {
560#pragma GCC diagnostic push
565#pragma GCC diagnostic ignored "-Wuninitialized"
566 memmove(
reinterpret_cast<char*
>(&this->uninitialized_get()),
567 &x.uninitialized_get(),
568 internal::used_size<internal::maybe_wrap_ref<T>>::value);
569#pragma GCC diagnostic pop
570 }
else if (_u.has_result()) {
571 this->uninitialized_set(std::move(x.uninitialized_get()));
572 std::destroy_at(&x.uninitialized_get());
576 [[gnu::always_inline]]
577 future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
578 move_it(std::move(x));
581 void clear() noexcept {
582 if (_u.has_result()) {
583 std::destroy_at(&this->uninitialized_get());
588 __attribute__((always_inline))
589 ~future_state() noexcept {
592 future_state& operator=(future_state&& x)
noexcept {
594 future_state_base::operator=(std::move(x));
597 move_it(std::move(x));
600 template <
typename... A>
601 future_state(ready_future_marker, A&&... a) noexcept : future_state_base(state::result) {
603 this->uninitialized_set(std::forward<A>(a)...);
605 new (
this) future_state(current_exception_future_marker());
608 template <
typename... A>
609 void set(A&&... a)
noexcept {
610 assert(_u.st == state::future);
611 new (
this) future_state(ready_future_marker(), std::forward<A>(a)...);
613 future_state(exception_future_marker, std::exception_ptr&& ex) noexcept : future_state_base(std::move(ex)) { }
614 future_state(exception_future_marker, future_state_base&& state) noexcept : future_state_base(std::move(state)) { }
615 future_state(current_exception_future_marker m) noexcept : future_state_base(m) { }
616 future_state(nested_exception_marker m, future_state_base&& old) noexcept : future_state_base(m, std::move(old)) { }
617 future_state(nested_exception_marker m, future_state_base&& n, future_state_base&& old) noexcept : future_state_base(m, std::move(n), std::move(old)) { }
618 T&& get_value() &&
noexcept {
619 assert(_u.st == state::result);
620 return static_cast<T&&
>(this->uninitialized_get());
622 T&& take_value() &&
noexcept {
623 assert(_u.st == state::result);
624 _u.st = state::result_unavailable;
625 return static_cast<T&&
>(this->uninitialized_get());
627 template<
typename U = T>
628 const std::enable_if_t<std::is_copy_constructible_v<U>, U>& get_value() const& noexcept(copy_noexcept) {
629 assert(_u.st == state::result);
630 return this->uninitialized_get();
634 if (_u.st >= state::exception_min) {
635 std::move(*this).rethrow_exception();
637 _u.st = state::result_unavailable;
638 return static_cast<T&&
>(this->uninitialized_get());
642 if (_u.st >= state::exception_min) {
643 std::move(*this).rethrow_exception();
645 return static_cast<T&&
>(this->uninitialized_get());
647 const T& get() const& {
649 if (_u.st >= state::exception_min) {
652 return this->uninitialized_get();
654 using get0_return_type =
typename internal::get0_return_type<T>::type;
655 static get0_return_type get0(T&& x) {
656 return internal::get0_return_type<T>::get0(std::move(x));
659 get0_return_type get0() {
660 return std::move(*this).get();
664template <
typename T =
void>
665class continuation_base :
public task {
667 using future_state = seastar::future_state<internal::future_stored_type_t<T>>;
669 using future_type = future<T>;
670 using promise_type = promise<T>;
672 continuation_base() noexcept = default;
673 void set_state(future_state&& state) noexcept {
674 _state = std::move(state);
680 virtual task* waiting_task() noexcept
override {
return nullptr; }
681 friend class internal::promise_base_with_type<T>;
682 friend class promise<T>;
683 friend class future<T>;
687template <
typename Future>
688struct continuation_base_from_future;
690template <
typename... T>
691struct continuation_base_from_future<future<T...>> {
692 using type = continuation_base<T...>;
695template <
typename Future>
696using continuation_base_from_future_t =
typename continuation_base_from_future<Future>::type;
698template <
typename Promise,
typename T =
void>
699class continuation_base_with_promise :
public continuation_base<T> {
700 friend class internal::promise_base_with_type<T>;
702 continuation_base_with_promise(Promise&& pr) noexcept : _pr(std::move(pr)) {
703 task::make_backtrace();
705 virtual task* waiting_task() noexcept override;
709template <typename Promise, typename Func, typename Wrapper, typename T =
void>
710struct continuation final : continuation_base_with_promise<Promise, T> {
721 continuation(Promise&& pr, Func&& func, Wrapper&& wrapper) noexcept
722 : continuation_base_with_promise<Promise, T>(std::move(pr))
723 , _func(std::move(func))
724 , _wrapper(std::move(wrapper)) {}
725 virtual void run_and_dispose() noexcept
override {
727 _wrapper(std::move(this->_pr), _func, std::move(this->_state));
729 this->_pr.set_to_current_exception();
734 [[no_unique_address]] Wrapper _wrapper;
739template <
typename T =
void>
742template <
typename T =
void>
743void set_callback(future<T>&& fut, continuation_base<T>* callback)
noexcept;
749 enum class urgent { no, yes };
750 future_base* _future =
nullptr;
755 future_state_base* _state;
757 task* _task =
nullptr;
758#ifdef SEASTAR_DEBUG_PROMISE
759 int _task_shard = -1;
761 void set_task(task* task)
noexcept {
765 void assert_task_shard() const noexcept;
767 void set_task(task* task)
noexcept {
770 void assert_task_shard() const noexcept { }
773 promise_base(
const promise_base&) =
delete;
774 promise_base(future_state_base* state) noexcept : _state(state) {}
775 promise_base(future_base* future, future_state_base* state)
noexcept;
776 void move_it(promise_base&& x)
noexcept;
777 promise_base(promise_base&& x)
noexcept;
779 void clear() noexcept;
783 ~promise_base() noexcept {
787 void operator=(
const promise_base&) =
delete;
788 promise_base& operator=(promise_base&& x)
noexcept;
790 template<urgent Urgent>
791 void make_ready() noexcept;
794 void set_exception_impl(T&& val) noexcept {
796 _state->set_exception(std::move(val));
797 make_ready<urgent::no>();
806 report_failed_future(val);
810 void set_exception(future_state_base&& state)
noexcept {
811 set_exception_impl(std::move(state));
814 void set_exception(std::exception_ptr&& ex)
noexcept {
815 set_exception_impl(std::move(ex));
818 void set_exception(
const std::exception_ptr& ex)
noexcept {
819 set_exception(std::exception_ptr(ex));
822 template<
typename Exception>
823 std::enable_if_t<!std::is_same_v<std::remove_reference_t<Exception>, std::exception_ptr>,
void> set_exception(Exception&& e)
noexcept {
824 set_exception(std::make_exception_ptr(std::forward<Exception>(e)));
827 friend class future_base;
835 void set_to_current_exception() noexcept;
838 task* waiting_task() const noexcept {
return _task; }
848class promise_base_with_type :
protected internal::promise_base {
850 using future_state = seastar::future_state<future_stored_type_t<T>>;
851 future_state* get_state() noexcept {
852 return static_cast<future_state*
>(_state);
854 static constexpr bool copy_noexcept = future_state::copy_noexcept;
856 promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
857 promise_base_with_type(future<T>* future) noexcept : promise_base(future, &future->_state) { }
858 promise_base_with_type(promise_base_with_type&& x)
noexcept =
default;
859 promise_base_with_type(
const promise_base_with_type&) =
delete;
860 promise_base_with_type& operator=(promise_base_with_type&& x)
noexcept =
default;
861 void operator=(
const promise_base_with_type&) =
delete;
863 void set_urgent_state(future_state&& state)
noexcept {
864 auto* ptr = get_state();
871 assert(ptr->_u.st == future_state_base::state::future);
872 new (ptr) future_state(std::move(state));
873 make_ready<urgent::yes>();
877 template <
typename... A>
878 void set_value(A&&... a)
noexcept {
879 if (
auto *s = get_state()) {
880 s->set(std::forward<A>(a)...);
881 make_ready<urgent::no>();
889 void set_to_current_exception() noexcept {
890 internal::promise_base::set_to_current_exception();
894 using internal::promise_base::waiting_task;
898 template <
typename U>
913class promise :
private internal::promise_base_with_type<T> {
914 using future_state =
typename internal::promise_base_with_type<T>::future_state;
915 future_state _local_state;
921 promise() noexcept : internal::promise_base_with_type<T>(&_local_state) {}
925 promise(
promise&& x) noexcept : internal::promise_base_with_type<T>(std::move(x)) {
926 move_it(std::move(x));
930 internal::promise_base_with_type<T>::operator=(std::move(x));
933 move_it(std::move(x));
936 void operator=(
const promise&) =
delete;
943 internal::promise_base::set_to_current_exception();
947 using internal::promise_base::waiting_task;
968 template <typename... A>
969 void set_value(A&&... a) noexcept {
970 internal::promise_base_with_type<T>::set_value(std::forward<A>(a)...);
978 internal::promise_base::set_exception(std::move(ex));
981 void set_exception(
const std::exception_ptr& ex)
noexcept {
982 internal::promise_base::set_exception(ex);
989 template<
typename Exception>
990 std::enable_if_t<!std::is_same_v<std::remove_reference_t<Exception>, std::exception_ptr>,
void>
set_exception(Exception&& e)
noexcept {
991 internal::promise_base::set_exception(std::forward<Exception>(e));
994 using internal::promise_base_with_type<T>::set_urgent_state;
996 template <
typename U>
1011template <
typename... T>
struct is_future : std::false_type {};
1015template <
typename... T>
struct is_future<
future<T...>> : std::true_type {};
1023SEASTAR_MODULE_EXPORT
1024template <
typename T>
1027template <
typename T>
1028concept Future = is_future<T>::value;
1030template <
typename Func,
typename... T>
1031concept CanInvoke = std::invocable<Func, T...>;
1034template <
typename Func,
typename... T>
1035concept CanApply = CanInvoke<Func, T...>;
1037template <
typename Func,
typename... T>
1038concept CanApplyTuple
1040 &&
requires (Func func, std::tuple<T...> wrapped_val) {
1041 { std::apply(func, std::get<0>(std::move(wrapped_val))) };
1045template <
typename Func,
typename Return,
typename... T>
1046concept InvokeReturns =
requires (Func f, T... args) {
1047 { f(std::forward<T>(args)...) } -> std::same_as<Return>;
1051template <
typename Func,
typename Return,
typename... T>
1052concept ApplyReturns = InvokeReturns<Func, Return, T...>;
1054template <
typename Func,
typename... T>
1055concept InvokeReturnsAnyFuture = Future<std::invoke_result_t<Func, T...>>;
1058template <
typename Func,
typename... T>
1059concept ApplyReturnsAnyFuture = InvokeReturnsAnyFuture<Func, T...>;
1064template <
typename T>
1065using futurize_t =
typename futurize<T>::type;
1069template<
typename Func,
typename... Args>
1070auto futurize_invoke(Func&& func, Args&&... args)
noexcept;
1072template<
typename Func,
typename... Args>
1073auto futurize_apply(Func&& func, std::tuple<Args...>&& args)
noexcept;
1080 promise_base* _promise;
1081 future_base() noexcept : _promise(
nullptr) {}
1082 future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
1083 _promise->_future =
this;
1084 _promise->_state = state;
1087 void move_it(future_base&& x, future_state_base* state)
noexcept {
1088 _promise = x._promise;
1089 if (
auto* p = _promise) {
1096 future_base(future_base&& x, future_state_base* state)
noexcept {
1097 move_it(std::move(x), state);
1100 void clear() noexcept {
1106 ~future_base() noexcept {
1110 promise_base* detach_promise() noexcept {
1111 _promise->_state =
nullptr;
1112 _promise->_future =
nullptr;
1113 return std::exchange(_promise,
nullptr);
1116 void schedule(task* tws, future_state_base* state)
noexcept {
1117 promise_base* p = detach_promise();
1122 void do_wait() noexcept;
1124 void set_coroutine(task& coroutine) noexcept;
1126 friend class promise_base;
1129template <typename Func, typename... T>
1130struct future_result {
1131 using type = std::invoke_result_t<Func, T...>;
1132 using future_type = futurize_t<type>;
1133 using func_type = future_type (T&&...);
1136template <
typename Func>
1137struct future_result<Func, void> {
1138 using type = std::invoke_result_t<Func>;
1139 using future_type = futurize_t<type>;
1140 using func_type = future_type ();
1143template <
typename Func,
typename T>
1144using future_result_t =
typename future_result<Func, T>::type;
1146template <
typename Func,
typename T>
1147auto future_invoke(Func&& func, T&& v) {
1148 if constexpr (std::is_same_v<T, monostate>) {
1149 return std::invoke(std::forward<Func>(func));
1151 return std::invoke(std::forward<Func>(func), std::forward<T>(v));
1155template <
typename Func,
typename... T>
1156struct result_of_apply {
1160template <
typename Func,
typename... T>
1161struct result_of_apply<Func,
std::tuple<T...>> : std::invoke_result<Func, T...> {
1165template <
typename Func,
typename... T>
1166using result_of_apply_t =
typename result_of_apply<Func, T...>::type;
1170template <
typename Promise,
typename T>
1171task* continuation_base_with_promise<Promise, T>::waiting_task() noexcept {
1172 return _pr.waiting_task();
1217SEASTAR_MODULE_EXPORT
1218template <
typename T>
1219class [[nodiscard]]
future :
private internal::future_base {
1220 using future_state = seastar::future_state<internal::future_stored_type_t<T>>;
1221 future_state _state;
1222 static constexpr bool copy_noexcept = future_state::copy_noexcept;
1233 future(
promise<T>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
1234 template <
typename... A>
1241 [[gnu::always_inline]]
1242 explicit future(future_state&& state) noexcept
1243 : _state(std::move(state)) {
1245 internal::promise_base_with_type<T> get_promise()
noexcept {
1247 return internal::promise_base_with_type<T>(
this);
1249 internal::promise_base_with_type<T>* detach_promise()
noexcept {
1250 return static_cast<internal::promise_base_with_type<T>*
>(future_base::detach_promise());
1252 void schedule(continuation_base<T>* tws)
noexcept {
1253 future_base::schedule(tws, &tws->_state);
1255 template <
typename Pr,
typename Func,
typename Wrapper>
1256 void schedule(Pr&& pr, Func&& func, Wrapper&& wrapper)
noexcept {
1262 auto tws =
new continuation<Pr, Func, Wrapper, T>(std::move(pr), std::move(func), std::move(wrapper));
1266 if (_state.available()) {
1267 tws->set_state(get_available_state_ref());
1268 ::seastar::schedule(tws);
1273 _state._u.st = future_state_base::state::invalid;
1276 [[gnu::always_inline]]
1277 future_state&& get_available_state_ref()
noexcept {
1281 return std::move(_state);
1288 future<T> rethrow_with_nested()
noexcept {
1292 template<
typename... U>
1297 using tuple_type = internal::future_tuple_type_t<value_type>;
1301 [[gnu::always_inline]]
1302 future(
future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1306 move_it(std::move(x), &_state);
1307 _state = std::move(x._state);
1310 void operator=(
const future&) =
delete;
1320 [[gnu::always_inline]]
1323 return get_available_state_ref().take();
1326 [[gnu::always_inline]]
1327 std::exception_ptr get_exception() noexcept {
1328 return get_available_state_ref().get_exception();
1352 [[deprecated(
"Use get() instead")]]
1363 if (_state.available()) {
1372 [[gnu::always_inline]]
1374 return _state.available();
1380 [[gnu::always_inline]]
1382 return _state.failed();
1400 template <typename Func, typename Result = typename internal::future_result<Func, T>::future_type>
1401 requires std::invocable<Func, T>
1402 || (std::same_as<void, T> && std::invocable<Func>)
1405#ifndef SEASTAR_TYPE_ERASE_MORE
1406 return then_impl(std::move(func));
1408 using func_type =
typename internal::future_result<Func, T>::func_type;
1413 return futurize_invoke(func, std::forward<
decltype(args)>(args)...);
1416 return then_impl(std::move(ncf));
1439 template <
typename Func,
typename Result = futurize_t<
internal::result_of_apply_t<Func, T>>>
1440 requires ::seastar::CanApplyTuple<Func, T>
1443 return then([func = std::forward<Func>(func)] (T&& tuple)
mutable {
1445 return std::apply(func, std::move(tuple));
1452 template <
typename Func,
typename Result>
1453 Result then_impl_nrvo(Func&& func)
noexcept {
1456 using pr_type =
decltype(fut.get_promise());
1457 schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1458 if (state.failed()) {
1459 pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1461 futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1465 return internal::future_invoke(func, std::move(state).get_value());
1472 template <
typename Func,
typename Result = futurize_t<
internal::future_result_t<Func, T>>>
1474 then_impl(Func&& func)
noexcept {
1475#ifndef SEASTAR_DEBUG
1476 using futurator = futurize<internal::future_result_t<Func, T>>;
1478 return futurator::make_exception_future(
static_cast<future_state_base&&
>(get_available_state_ref()));
1479 }
else if (available()) {
1480 return futurator::invoke(std::forward<Func>(func), get_available_state_ref().take_value());
1483 return then_impl_nrvo<Func, Result>(std::forward<Func>(func));
1502 template <std::invocable<future> Func,
typename FuncResult = std::invoke_result_t<Func, future>>
1503 futurize_t<FuncResult>
1505 return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1508 template <std::invocable<future&&> Func,
typename FuncResult = std::invoke_result_t<Func, future&&>>
1509 futurize_t<FuncResult>
1510 then_wrapped(Func&& func) &&
noexcept {
1511 return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1516 template <
bool AsSelf,
typename FuncResult,
typename Func>
1517 futurize_t<FuncResult>
1518 then_wrapped_maybe_erase(Func&& func)
noexcept {
1519#ifndef SEASTAR_TYPE_ERASE_MORE
1520 return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1522 using futurator = futurize<FuncResult>;
1523 using WrapFuncResult =
typename futurator::type;
1524 noncopyable_function<WrapFuncResult (future&&)> ncf;
1526 memory::scoped_critical_alloc_section _;
1527 ncf = noncopyable_function<WrapFuncResult(future &&)>([func = std::forward<Func>(func)](future&& f)
mutable {
1528 return futurator::invoke(func, std::move(f));
1531 return then_wrapped_common<AsSelf, WrapFuncResult>(std::move(ncf));
1536 template <
typename FuncResult,
typename Func>
1537 futurize_t<FuncResult>
1538 then_wrapped_nrvo(Func&& func)
noexcept {
1539 using futurator = futurize<FuncResult>;
1540 typename futurator::type fut(future_for_get_promise_marker{});
1541 using pr_type =
decltype(fut.get_promise());
1542 schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1543 futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1544 return func(future(std::move(state)));
1551 template <
bool AsSelf,
typename FuncResult,
typename Func>
1552 futurize_t<FuncResult>
1553 then_wrapped_common(Func&& func)
noexcept {
1554#ifndef SEASTAR_DEBUG
1555 using futurator = futurize<FuncResult>;
1557 if constexpr (AsSelf) {
1561 return futurator::invoke(std::forward<Func>(func), std::move(*
this));
1563 return futurator::invoke(std::forward<Func>(func), future(get_available_state_ref()));
1567 return then_wrapped_nrvo<FuncResult, Func>(std::forward<Func>(func));
1570 void forward_to(internal::promise_base_with_type<T>&& pr)
noexcept {
1571 if (_state.available()) {
1572 pr.set_urgent_state(std::move(_state));
1574 *detach_promise() = std::move(pr);
1590 if (_state.available()) {
1591 pr.set_urgent_state(std::move(_state));
1592 }
else if (&pr._local_state != pr._state) {
1597 *detach_promise() = std::move(pr);
1618 template <std::invocable Func>
1620 return then_wrapped(
finally_body<Func,
is_future<std::invoke_result_t<Func>>::value>(std::forward<Func>(func)));
1624 template <
typename Func,
bool FuncReturnsFuture>
1627 template <
typename Func>
1631 finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1635 return futurize_invoke(_func).then_wrapped([result = std::move(result)](
auto&& f_res)
mutable {
1636 if (!f_res.failed()) {
1637 return std::move(result);
1639 return result.rethrow_with_nested(std::move(f_res._state));
1645 template <
typename Func>
1649 finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1655 return std::move(result);
1657 return result.rethrow_with_nested();
1667 return then_wrapped([] (
auto&& f) {
1671 engine_exit(std::current_exception());
1683 return then([] (
auto&&...) {});
1699 template <
typename Func>
1700 requires std::is_invocable_r_v<future<T> ,Func, std::exception_ptr>
1701 || (std::tuple_size_v<tuple_type> == 0 && std::is_invocable_r_v<void, Func, std::exception_ptr>)
1702 || (std::tuple_size_v<tuple_type> == 1 && std::is_invocable_r_v<T, Func, std::exception_ptr>)
1703 || (std::tuple_size_v<tuple_type> > 1 && std::is_invocable_r_v<tuple_type ,Func, std::exception_ptr>)
1705 return then_wrapped([func = std::forward<Func>(func)]
1707 if (!fut.failed()) {
1708 return make_ready_future<T>(fut.get());
1710 return futurize_invoke(func, fut.get_exception());
1725 template <
typename Func>
1728 static_assert(trait::arity == 1,
"func can take only one parameter");
1729 using ex_type =
typename trait::template arg<0>::type;
1730 return then_wrapped([func = std::forward<Func>(func)]
1733 return make_ready_future<T>(fut.get());
1734 }
catch(ex_type& ex) {
1735 return futurize_invoke(func, ex);
1749 using future_base::set_coroutine;
1752 void set_task(
task& t)
noexcept {
1754 _promise->set_task(&t);
1757 void set_callback(continuation_base<T>* callback)
noexcept {
1758 if (_state.available()) {
1759 callback->set_state(get_available_state_ref());
1760 ::seastar::schedule(callback);
1769 template <
typename U>
1770 friend class future;
1771 template <
typename U>
1772 friend class promise;
1773 template <
typename U>
1774 friend struct futurize;
1775 template <
typename U>
1776 friend class internal::promise_base_with_type;
1777 template <
typename U,
typename... A>
1779 template <
typename U>
1781 template <
typename U,
typename Exception>
1783 template <
typename U>
1784 friend future<U> internal::make_exception_future(future_state_base&& state)
noexcept;
1785 template <
typename U>
1787 template <typename U>
1788 friend
void internal::set_callback(future<U>&&, continuation_base<U>*) noexcept;
1794template <
typename T>
1795struct futurize_base {
1797 using type = future<T>;
1799 using promise_type = promise<T>;
1800 using promise_base_with_type = internal::promise_base_with_type<T>;
1803 static inline type convert(T&& value) {
return make_ready_future<T>(std::move(value)); }
1804 static inline type convert(type&& value) {
return std::move(value); }
1807 template <
typename Arg>
1812struct futurize_base<void> {
1813 using type = future<>;
1815 using promise_base_with_type = internal::promise_base_with_type<>;
1817 static inline type convert(type&& value) {
1818 return std::move(value);
1820 template <
typename Arg>
1824template <
typename T>
1825struct futurize_base<future<T>> :
public futurize_base<T> {};
1828struct futurize_base<future<>> :
public futurize_base<void> {};
1831template <
typename T>
1833 using base = internal::futurize_base<T>;
1836 using promise_base_with_type =
typename base::promise_base_with_type;
1839 using tuple_type =
typename type::tuple_type;
1840 using base::convert;
1841 using base::make_exception_future;
1845 template<
typename Func,
typename... FuncArgs>
1846 static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args)
noexcept;
1850 template<
typename Func,
typename... FuncArgs>
1851 static inline type invoke(Func&& func, FuncArgs&&... args)
noexcept;
1853 template<
typename Func>
1854 static inline type invoke(Func&& func, internal::monostate)
noexcept {
1855 return invoke(std::forward<Func>(func));
1859 template<
typename Func,
typename... FuncArgs>
1860 [[deprecated(
"Use invoke for varargs")]]
1861 static inline type apply(Func&& func, FuncArgs&&... args)
noexcept {
1862 return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1890 template<std::invocable Func>
1891 static void satisfy_with_result_of(promise_base_with_type&&, Func&& func);
1893 template <
typename U>
1897inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1898 : _future(future), _state(state) {
1899 _future->_promise =
this;
1902template <
typename T>
1906 assert(!this->_future && this->_state && !this->_task);
1910template <
typename T>
1913 if (this->_state == &x._local_state) {
1914 this->_state = &_local_state;
1915 new (&_local_state) future_state(std::move(x._local_state));
1919SEASTAR_MODULE_EXPORT_BEGIN
1920template <
typename T,
typename... A>
1926template <
typename T>
1931SEASTAR_MODULE_EXPORT_END
1933template <
typename T>
1935future<T> internal::make_exception_future(future_state_base&& state)
noexcept {
1936 return future<T>(exception_future_marker(), std::move(state));
1939SEASTAR_MODULE_EXPORT_BEGIN
1940template <
typename T>
1945void log_exception_trace() noexcept;
1953template <typename T, typename Exception>
1956 log_exception_trace();
1957 return make_exception_future<T>(std::make_exception_ptr(std::forward<Exception>(ex)));
1960template <
typename T,
typename Exception>
1961future<T> make_exception_future_with_backtrace(Exception&& ex)
noexcept {
1962 return make_exception_future<T>(make_backtraced_exception_ptr<Exception>(std::forward<Exception>(ex)));
1964SEASTAR_MODULE_EXPORT_END
1971template<
typename Func,
typename... FuncArgs>
1972typename futurize<T>::type
futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args)
noexcept {
1974 using ret_t =
decltype(std::apply(std::forward<Func>(func), std::move(args)));
1975 if constexpr (std::is_void_v<ret_t>) {
1976 std::apply(std::forward<Func>(func), std::move(args));
1977 return make_ready_future<>();
1978 }
else if constexpr (is_future<ret_t>::value){
1979 return std::apply(std::forward<Func>(func), std::move(args));
1981 return convert(std::apply(std::forward<Func>(func), std::move(args)));
1989template<std::invocable Func>
1990void futurize<T>::satisfy_with_result_of(promise_base_with_type&& pr, Func&& func) {
1991 using ret_t =
decltype(func());
1992 if constexpr (std::is_void_v<ret_t>) {
1995 }
else if constexpr (is_future<ret_t>::value) {
1996 func().forward_to(std::move(pr));
2003template<
typename Func,
typename... FuncArgs>
2006 using ret_t =
decltype(func(std::forward<FuncArgs>(args)...));
2007 if constexpr (std::is_void_v<ret_t>) {
2008 func(std::forward<FuncArgs>(args)...);
2009 return make_ready_future<>();
2010 }
else if constexpr (is_future<ret_t>::value) {
2011 return func(std::forward<FuncArgs>(args)...);
2013 return convert(func(std::forward<FuncArgs>(args)...));
2020template <
typename T>
2021template <
typename Arg>
2024internal::futurize_base<T>::make_exception_future(Arg&& arg)
noexcept {
2025 using ::seastar::make_exception_future;
2026 using ::seastar::internal::make_exception_future;
2027 return make_exception_future<T>(std::forward<Arg>(arg));
2030template <
typename Arg>
2033internal::futurize_base<void>::make_exception_future(Arg&& arg)
noexcept {
2034 using ::seastar::make_exception_future;
2035 using ::seastar::internal::make_exception_future;
2036 return make_exception_future<>(std::forward<Arg>(arg));
2039template<
typename Func,
typename... Args>
2040auto futurize_invoke(Func&& func, Args&&... args)
noexcept {
2041 using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2042 return futurator::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2045template<
typename Func,
typename... Args>
2046[[deprecated(
"Use futurize_invoke for varargs")]]
2047auto futurize_apply(Func&& func, Args&&... args)
noexcept {
2048 return futurize_invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2051template<
typename Func,
typename... Args>
2052auto futurize_apply(Func&& func, std::tuple<Args...>&& args)
noexcept {
2053 using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2054 return futurator::apply(std::forward<Func>(func), std::move(args));
2059template <
typename T>
2061void set_callback(future<T>&& fut, continuation_base<T>* callback)
noexcept {
2062 return std::move(fut).set_callback(callback);
A representation of a possibly not-yet-computed value.
Definition: future.hh:1219
futurize_t< FuncResult > then_wrapped(Func &&func) &noexcept
Schedule a block of code to run when the future is ready, allowing for exception handling.
Definition: future.hh:1504
future< T > handle_exception_type(Func &&func) noexcept
Handle the exception of a certain type carried by this future.
Definition: future.hh:1726
void wait() noexcept
Definition: future.hh:1362
internal::future_stored_type_t< T > value_type
The data type carried by the future.
Definition: future.hh:1296
future< T > handle_exception(Func &&func) noexcept
Handle the exception carried by this future.
Definition: future.hh:1704
Result then(Func &&func) noexcept
Schedule a block of code to run when the future is ready.
Definition: future.hh:1404
value_type && get()
gets the value returned by the computation
Definition: future.hh:1321
bool failed() const noexcept
Checks whether the future has failed.
Definition: future.hh:1381
requires ::seastar::CanApplyTuple< Func, T > Result then_unpack(Func &&func) noexcept
Schedule a block of code to run when the future is ready, unpacking tuples.
Definition: future.hh:1442
bool available() const noexcept
Checks whether the future is available.
Definition: future.hh:1373
typename future_state::get0_return_type get0_return_type
Definition: future.hh:1351
void forward_to(promise< T > &&pr) noexcept
Satisfy some promise object with this future as a result.
Definition: future.hh:1589
future(future &&x) noexcept
Moves the future into a new object.
Definition: future.hh:1302
future discard_result() noexcept
Discards the value carried by this future.
Definition: future.hh:1680
future or_terminate() noexcept
Terminate the program if this future fails.
Definition: future.hh:1666
void ignore_ready_future() noexcept
Ignore any result hold by this future.
Definition: future.hh:1745
Definition: future.hh:1625
promise - allows a future value to be made available at a later time.
Definition: future.hh:913
void set_to_current_exception() noexcept
Definition: future.hh:942
std::enable_if_t<!std::is_same_v< std::remove_reference_t< Exception >, std::exception_ptr >, void > set_exception(Exception &&e) noexcept
Marks the promise as failed.
Definition: future.hh:990
void set_value(A &&... a) noexcept
Sets the promises value.
Definition: future.hh:969
void set_exception(std::exception_ptr &&ex) noexcept
Marks the promise as failed.
Definition: future.hh:977
promise() noexcept
Constructs an empty promise.
Definition: future.hh:921
Like future except the result can be waited for by many fibers.
Definition: shared_future.hh:108
future< T > make_ready_future(A &&... value) noexcept
Creates a future in an available, value state.
Definition: future.hh:1922
future< T > get_future() noexcept
Gets the promise's associated future.
Definition: future.hh:1905
future< std::remove_cv_t< std::remove_reference_t< T > > > as_ready_future(T &&v) noexcept
Returns a ready future that is already resolved.
Definition: future.hh:173
future< T > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1928
future< T > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:1941
void move_it(promise &&x) noexcept
Moves a promise object.
Definition: future.hh:1912
Definition: future.hh:545
Definition: future.hh:546
Definition: future.hh:544
Definition: critical_alloc_section.hh:80
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
shard_id this_shard_id() noexcept
Returns shard_id of the of the current shard.
Definition: shard_id.hh:52
Definition: noncopyable_function.hh:37
Definition: function_traits.hh:62
Exception type for broken promises.
Definition: future.hh:222
Definition: future.hh:398
friend future< U > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:1941
Definition: future.hh:490
Definition: future.hh:492
Converts a type to a future type, if it isn't already.
Definition: future.hh:1832
static type apply(Func &&func, FuncArgs &&... args) noexcept
Deprecated alias of invoke.
Definition: future.hh:1861
static type from_tuple(tuple_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:1870
static type from_tuple(value_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:1879
static type apply(Func &&func, std::tuple< FuncArgs... > &&args) noexcept
static type from_tuple(const value_type &value)
Convert the tuple representation into a future.
Definition: future.hh:1883
static type from_tuple(const tuple_type &value)
Convert the tuple representation into a future.
Definition: future.hh:1874
typename type::value_type value_type
The value tuple type associated with type.
Definition: future.hh:1838
static type invoke(Func &&func, FuncArgs &&... args) noexcept
Check whether a type is a future.
Definition: future.hh:1011
Definition: future.hh:414