24 #include <seastar/core/task.hh>
25 #include <seastar/core/thread_impl.hh>
29 #include <type_traits>
32 #include <seastar/core/function_traits.hh>
33 #include <seastar/util/critical_alloc_section.hh>
34 #include <seastar/util/attribute-compat.hh>
35 #include <seastar/util/concepts.hh>
36 #include <seastar/util/noncopyable_function.hh>
37 #include <seastar/util/backtrace.hh>
39 #if __cplusplus > 201703L
46 std::exception_ptr inner;
47 std::exception_ptr outer;
48 nested_exception(std::exception_ptr inner, std::exception_ptr outer) noexcept;
51 [[noreturn]]
void rethrow_nested()
const;
52 virtual const char* what()
const noexcept
override;
146 #if SEASTAR_API_LEVEL < 6
147 template <
class... T>
149 template <
class T =
void>
153 template <
class SEASTAR_ELLIPSIS T>
156 template <
typename... T>
167 template <
typename... T,
typename... A>
176 template <
typename... T>
179 template <
typename... T>
184 template <
typename... T>
190 void engine_exit(std::exception_ptr eptr = {});
192 void report_failed_future(
const std::exception_ptr& ex) noexcept;
194 void report_failed_future(
const future_state_base& state) noexcept;
196 void with_allow_abandoned_failed_futures(
unsigned count, noncopyable_function<
void ()> func);
215 template <
typename... T>
222 #if SEASTAR_API_LEVEL < 6
223 template <
class... T>
225 template <
class T =
void>
227 class promise_base_with_type;
232 template <
typename... T>
233 struct future_stored_type;
236 struct future_stored_type<> {
237 #if SEASTAR_API_LEVEL < 5
238 using type = std::tuple<>;
240 using type = monostate;
244 template <
typename T>
245 struct future_stored_type<T> {
246 #if SEASTAR_API_LEVEL < 5
247 using type = std::tuple<T>;
249 using type = std::conditional_t<std::is_void_v<T>, internal::monostate, T>;
253 template <
typename... T>
254 using future_stored_type_t =
typename future_stored_type<T...>::type;
257 #if SEASTAR_API_LEVEL < 5
258 using future_tuple_type_t = T;
260 using future_tuple_type_t = std::conditional_t<std::is_same_v<T, monostate>, std::tuple<>, std::tuple<T>>;
265 template <
typename T>
266 struct get0_return_type;
269 struct get0_return_type<std::tuple<>> {
271 static type get0(std::tuple<> v) { }
274 template <
typename T0,
typename... T>
275 struct get0_return_type<std::tuple<T0, T...>> {
277 static type get0(std::tuple<T0, T...> v) {
return std::get<0>(std::move(v)); }
281 using maybe_wrap_ref = std::conditional_t<std::is_reference_v<T>, std::reference_wrapper<std::remove_reference_t<T>>, T>;
290 template <
typename T,
bool is_trivial_
class>
291 struct uninitialized_wrapper_base;
293 template <
typename T>
294 struct uninitialized_wrapper_base<T, false> {
295 using tuple_type = future_tuple_type_t<T>;
300 maybe_wrap_ref<T> value;
304 uninitialized_wrapper_base() noexcept = default;
305 template<typename... U>
306 std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>,
void>
307 uninitialized_set(U&&... vs) {
308 new (&_v.value) maybe_wrap_ref<T>{T(std::forward<U>(vs)...)};
310 void uninitialized_set(tuple_type&& v) {
311 uninitialized_set(std::move(std::get<0>(v)));
313 void uninitialized_set(
const tuple_type& v) {
314 uninitialized_set(std::get<0>(v));
316 maybe_wrap_ref<T>& uninitialized_get() {
319 const maybe_wrap_ref<T>& uninitialized_get()
const {
324 template <
typename T>
struct uninitialized_wrapper_base<T, true> :
private T {
325 using tuple_type = future_tuple_type_t<T>;
326 uninitialized_wrapper_base() noexcept = default;
327 template<typename... U>
328 std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>,
void>
329 uninitialized_set(U&&... vs) {
330 new (
this) T(std::forward<U>(vs)...);
332 void uninitialized_set(tuple_type&& v) {
333 if constexpr (std::tuple_size_v<tuple_type> != 0) {
334 uninitialized_set(std::move(std::get<0>(v)));
337 void uninitialized_set(
const tuple_type& v) {
338 if constexpr (std::tuple_size_v<tuple_type> != 0) {
339 uninitialized_set(std::get<0>(v));
342 T& uninitialized_get() {
345 const T& uninitialized_get()
const {
350 template <
typename T>
351 constexpr
bool can_inherit =
352 #ifdef _LIBCPP_VERSION
359 std::is_same<std::tuple<>, T>::value ||
361 (std::is_trivially_destructible<T>::value && std::is_trivially_constructible<T>::value &&
362 std::is_class<T>::value && !std::is_final<T>::value);
366 template <
typename T>
367 struct uninitialized_wrapper
368 :
public uninitialized_wrapper_base<T, can_inherit<T>> {};
370 template <
typename T>
371 struct is_trivially_move_constructible_and_destructible {
372 static constexpr
bool value = std::is_trivially_move_constructible<T>::value && std::is_trivially_destructible<T>::value;
376 struct all_true : std::false_type {};
379 struct all_true<> : std::true_type {};
382 struct all_true<true, v...> :
public all_true<v...> {};
385 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper;
387 template <
typename... T>
388 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper<std::tuple<T...>> {
389 static constexpr
bool value = all_true<is_trivially_move_constructible_and_destructible<T>::value...>::value;
392 template <
typename T>
393 static constexpr
bool is_tuple_effectively_trivially_move_constructible_and_destructible =
394 is_tuple_effectively_trivially_move_constructible_and_destructible_helper<T>::value;
426 static_assert(
sizeof(std::exception_ptr) ==
sizeof(
void*),
"exception_ptr not a pointer");
427 enum class state : uintptr_t {
437 result_unavailable = 2,
442 any() noexcept { st = state::future; }
443 any(state s) noexcept { st = s; }
444 void set_exception(std::exception_ptr&& e) noexcept {
445 new (&ex) std::exception_ptr(std::move(e));
446 assert(st >= state::exception_min);
448 any(std::exception_ptr&& e) noexcept {
449 set_exception(std::move(e));
452 bool valid()
const noexcept {
return st != state::invalid && st != state::result_unavailable; }
453 bool available()
const noexcept {
return st == state::result || st >= state::exception_min; }
454 bool failed()
const noexcept {
return __builtin_expect(st >= state::exception_min,
false); }
455 void check_failure() noexcept;
457 std::exception_ptr take_exception() noexcept {
458 std::exception_ptr ret(std::move(ex));
471 void move_it(
any&& x) noexcept {
480 memmove(
static_cast<void*
>(
this), &x,
sizeof(
any));
481 x.st = state::invalid;
483 if (x.st < state::exception_min) {
485 x.st = state::invalid;
487 new (&ex) std::exception_ptr(x.take_exception());
492 move_it(std::move(x));
494 any& operator=(
any&& x) noexcept {
499 move_it(std::move(x));
502 bool has_result()
const noexcept {
503 return st == state::result || st == state::result_unavailable;
506 std::exception_ptr ex;
512 future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
524 void rethrow_exception() &&;
525 void rethrow_exception() const&;
529 bool valid() const noexcept {
return _u.valid(); }
530 bool available() const noexcept {
return _u.available(); }
531 bool failed() const noexcept {
return _u.failed(); }
533 void ignore() noexcept;
535 void set_exception(std::exception_ptr&& ex) noexcept {
536 assert(_u.st == state::future);
537 _u.set_exception(std::move(ex));
539 future_state_base& operator=(future_state_base&& x) noexcept =
default;
540 void set_exception(future_state_base&& state) noexcept {
541 assert(_u.st == state::future);
542 *
this = std::move(state);
544 std::exception_ptr get_exception() && noexcept {
545 assert(_u.st >= state::exception_min);
547 return _u.take_exception();
549 const std::exception_ptr& get_exception() const& noexcept {
550 assert(_u.st >= state::exception_min);
553 template <
typename U>
554 friend struct future_state;
555 template <
typename... U>
557 template <typename SEASTAR_ELLIPSIS U>
559 template <typename T>
560 friend struct futurize;
563 void report_failed_future(future_state_base::any&& state) noexcept;
565 inline
void future_state_base::any::check_failure() noexcept {
567 report_failed_future(std::move(*
this));
576 template <
typename T>
577 struct future_state :
public future_state_base,
private internal::uninitialized_wrapper<T> {
578 static constexpr
bool copy_noexcept = std::is_nothrow_copy_constructible<T>::value;
579 #if SEASTAR_API_LEVEL < 5
580 static constexpr
bool has_trivial_move_and_destroy = internal::is_tuple_effectively_trivially_move_constructible_and_destructible<T>;
582 static constexpr
bool has_trivial_move_and_destroy = internal::is_trivially_move_constructible_and_destructible<T>::value;
584 static_assert(std::is_nothrow_move_constructible<T>::value,
585 "Types must be no-throw move constructible");
586 static_assert(std::is_nothrow_destructible<T>::value,
587 "Types must be no-throw destructible");
588 future_state() noexcept = default;
589 void move_it(future_state&& x) noexcept {
590 if constexpr (has_trivial_move_and_destroy) {
591 memmove(
reinterpret_cast<char*
>(&this->uninitialized_get()),
592 &x.uninitialized_get(),
593 internal::used_size<internal::maybe_wrap_ref<T>>::value);
594 }
else if (_u.has_result()) {
595 this->uninitialized_set(std::move(x.uninitialized_get()));
596 std::destroy_at(&x.uninitialized_get());
600 [[gnu::always_inline]]
601 future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
602 move_it(std::move(x));
605 void clear() noexcept {
606 if (_u.has_result()) {
607 std::destroy_at(&this->uninitialized_get());
612 __attribute__((always_inline))
613 ~future_state() noexcept {
616 future_state& operator=(future_state&& x) noexcept {
618 future_state_base::operator=(std::move(x));
621 move_it(std::move(x));
624 template <
typename... A>
625 future_state(ready_future_marker, A&&... a) noexcept : future_state_base(state::result) {
627 this->uninitialized_set(std::forward<A>(a)...);
629 new (
this) future_state(current_exception_future_marker());
632 template <
typename... A>
633 void set(A&&... a) noexcept {
634 assert(_u.st == state::future);
635 new (
this) future_state(ready_future_marker(), std::forward<A>(a)...);
637 future_state(exception_future_marker m, std::exception_ptr&& ex) noexcept : future_state_base(std::move(ex)) { }
638 future_state(exception_future_marker m, future_state_base&& state) noexcept : future_state_base(std::move(state)) { }
639 future_state(current_exception_future_marker m) noexcept : future_state_base(m) { }
640 future_state(nested_exception_marker m, future_state_base&& old) noexcept : future_state_base(m, std::move(old)) { }
641 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)) { }
642 T&& get_value() && noexcept {
643 assert(_u.st == state::result);
644 return static_cast<T&&
>(this->uninitialized_get());
646 T&& take_value() && noexcept {
647 assert(_u.st == state::result);
648 _u.st = state::result_unavailable;
649 return static_cast<T&&
>(this->uninitialized_get());
651 template<
typename U = T>
652 const std::enable_if_t<std::is_copy_constructible<U>::value, U>& get_value() const& noexcept(copy_noexcept) {
653 assert(_u.st == state::result);
654 return this->uninitialized_get();
658 if (_u.st >= state::exception_min) {
659 std::move(*this).rethrow_exception();
661 _u.st = state::result_unavailable;
662 return static_cast<T&&
>(this->uninitialized_get());
666 if (_u.st >= state::exception_min) {
667 std::move(*this).rethrow_exception();
669 return static_cast<T&&
>(this->uninitialized_get());
671 const T& get() const& {
673 if (_u.st >= state::exception_min) {
676 return this->uninitialized_get();
678 using get0_return_type =
typename internal::get0_return_type<internal::future_tuple_type_t<T>>::type;
679 static get0_return_type get0(T&& x) {
680 return internal::get0_return_type<T>::get0(std::move(x));
683 get0_return_type get0() {
684 #if SEASTAR_API_LEVEL < 5
685 return get0(std::move(*this).get());
687 return std::move(*this).get();
692 #if SEASTAR_API_LEVEL < 6
693 template <
typename... T>
695 template <
typename T =
void>
697 class continuation_base :
public task {
699 using future_state = seastar::future_state<internal::future_stored_type_t<T SEASTAR_ELLIPSIS>>;
701 using future_type = future<T SEASTAR_ELLIPSIS>;
702 using promise_type = promise<T SEASTAR_ELLIPSIS>;
704 continuation_base() noexcept = default;
705 void set_state(future_state&& state) noexcept {
706 _state = std::move(state);
712 virtual task* waiting_task() noexcept
override {
return nullptr; }
713 friend class internal::promise_base_with_type<T SEASTAR_ELLIPSIS>;
714 friend class promise<T SEASTAR_ELLIPSIS>;
715 friend class future<T SEASTAR_ELLIPSIS>;
719 template <
typename Future>
720 struct continuation_base_from_future;
722 template <
typename... T>
723 struct continuation_base_from_future<future<T...>> {
724 using type = continuation_base<T...>;
727 template <
typename Future>
728 using continuation_base_from_future_t =
typename continuation_base_from_future<Future>::type;
730 #if SEASTAR_API_LEVEL < 6
731 template <
typename Promise,
typename... T>
733 template <
typename Promise,
typename T =
void>
735 class continuation_base_with_promise :
public continuation_base<T SEASTAR_ELLIPSIS> {
736 friend class internal::promise_base_with_type<T SEASTAR_ELLIPSIS>;
738 continuation_base_with_promise(Promise&& pr) noexcept : _pr(std::move(pr)) {
739 task::make_backtrace();
741 virtual task* waiting_task() noexcept override;
745 #if SEASTAR_API_LEVEL < 6
746 template <
typename Promise,
typename Func,
typename Wrapper,
typename... T>
748 template <
typename Promise,
typename Func,
typename Wrapper,
typename T =
void>
750 struct continuation final : continuation_base_with_promise<Promise, T SEASTAR_ELLIPSIS> {
761 continuation(Promise&& pr, Func&& func, Wrapper&& wrapper) noexcept
762 : continuation_base_with_promise<Promise, T SEASTAR_ELLIPSIS>(std::move(pr))
763 , _func(std::move(func))
764 , _wrapper(std::move(wrapper)) {}
765 virtual void run_and_dispose() noexcept
override {
767 _wrapper(std::move(this->_pr), _func, std::move(this->_state));
769 this->_pr.set_to_current_exception();
774 [[no_unique_address]] Wrapper _wrapper;
777 #if SEASTAR_API_LEVEL < 4
786 template <
typename... T>
787 struct when_all_succeed_tuple : std::tuple<T...> {
788 using std::tuple<T...>::tuple;
789 when_all_succeed_tuple(std::tuple<T...>&& t)
790 noexcept(std::is_nothrow_move_constructible<std::tuple<T...>>::value)
791 : std::tuple<T...>(std::move(t)) {}
798 template <
typename... T>
801 template <
typename... T,
typename U>
802 void set_callback(future<T...>& fut, U* callback) noexcept;
808 enum class urgent { no, yes };
809 future_base* _future =
nullptr;
814 future_state_base* _state;
816 task* _task =
nullptr;
818 promise_base(
const promise_base&) =
delete;
819 promise_base(future_state_base* state) noexcept : _state(state) {}
820 promise_base(future_base* future, future_state_base* state) noexcept;
821 void move_it(promise_base&& x) noexcept;
822 promise_base(promise_base&& x) noexcept;
824 void clear() noexcept;
828 ~promise_base() noexcept {
832 void operator=(
const promise_base&) =
delete;
833 promise_base& operator=(promise_base&& x) noexcept;
835 template<urgent Urgent>
836 void make_ready() noexcept;
839 void set_exception_impl(T&& val) noexcept {
841 _state->set_exception(std::move(val));
842 make_ready<urgent::no>();
851 report_failed_future(val);
855 void set_exception(future_state_base&& state) noexcept {
856 set_exception_impl(std::move(state));
859 void set_exception(std::exception_ptr&& ex) noexcept {
860 set_exception_impl(std::move(ex));
863 void set_exception(
const std::exception_ptr& ex) noexcept {
864 set_exception(std::exception_ptr(ex));
867 template<
typename Exception>
868 std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value,
void> set_exception(Exception&& e) noexcept {
869 set_exception(make_exception_ptr(std::forward<Exception>(e)));
872 friend class future_base;
880 void set_to_current_exception() noexcept;
883 task* waiting_task() const noexcept {
return _task; }
892 template <
typename SEASTAR_ELLIPSIS T>
893 class promise_base_with_type :
protected internal::promise_base {
895 using future_state = seastar::future_state<future_stored_type_t<T SEASTAR_ELLIPSIS>>;
896 future_state* get_state() noexcept {
897 return static_cast<future_state*
>(_state);
899 static constexpr
bool copy_noexcept = future_state::copy_noexcept;
901 promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
902 promise_base_with_type(future<T SEASTAR_ELLIPSIS>* future) noexcept : promise_base(future, &future->_state) { }
903 promise_base_with_type(promise_base_with_type&& x) noexcept =
default;
904 promise_base_with_type(
const promise_base_with_type&) =
delete;
905 promise_base_with_type& operator=(promise_base_with_type&& x) noexcept =
default;
906 void operator=(
const promise_base_with_type&) =
delete;
908 void set_urgent_state(future_state&& state) noexcept {
909 auto* ptr = get_state();
916 assert(ptr->_u.st == future_state_base::state::future);
917 new (ptr) future_state(std::move(state));
918 make_ready<urgent::yes>();
922 template <
typename... A>
923 void set_value(A&&... a) noexcept {
924 if (
auto *s = get_state()) {
925 s->set(std::forward<A>(a)...);
926 make_ready<urgent::no>();
934 void set_to_current_exception() noexcept {
935 internal::promise_base::set_to_current_exception();
939 using internal::promise_base::waiting_task;
943 template <
typename SEASTAR_ELLIPSIS U>
956 template <
typename SEASTAR_ELLIPSIS T>
957 class promise :
private internal::promise_base_with_type<T SEASTAR_ELLIPSIS> {
958 using future_state =
typename internal::promise_base_with_type<T SEASTAR_ELLIPSIS>::future_state;
959 future_state _local_state;
965 promise() noexcept : internal::promise_base_with_type<T SEASTAR_ELLIPSIS>(&_local_state) {}
969 promise(
promise&& x) noexcept : internal::promise_base_with_type<T SEASTAR_ELLIPSIS>(std::move(x)) {
970 move_it(std::move(x));
974 internal::promise_base_with_type<T SEASTAR_ELLIPSIS>::operator=(std::move(x));
977 move_it(std::move(x));
980 void operator=(
const promise&) =
delete;
987 internal::promise_base::set_to_current_exception();
991 using internal::promise_base::waiting_task;
1012 template <typename... A>
1013 void set_value(A&&... a) noexcept {
1014 internal::promise_base_with_type<T SEASTAR_ELLIPSIS>::set_value(std::forward<A>(a)...);
1022 internal::promise_base::set_exception(std::move(ex));
1025 void set_exception(
const std::exception_ptr& ex) noexcept {
1026 internal::promise_base::set_exception(ex);
1033 template<
typename Exception>
1034 std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value,
void>
set_exception(Exception&& e) noexcept {
1035 internal::promise_base::set_exception(std::forward<Exception>(e));
1038 using internal::promise_base_with_type<T SEASTAR_ELLIPSIS>::set_urgent_state;
1040 template <
typename SEASTAR_ELLIPSIS U>
1044 #if SEASTAR_API_LEVEL < 6
1051 class promise<void> :
public promise<> {};
1065 template <
typename... T>
struct is_future : std::false_type {};
1069 template <
typename... T>
struct is_future<
future<T...>> : std::true_type {};
1077 template <
typename T>
1082 template <typename T>
1083 concept Future = is_future<T>::value;
1085 template <
typename Func,
typename... T>
1086 concept CanInvoke = std::invocable<Func, T...>;
1089 template <
typename Func,
typename... T>
1090 concept CanApply = CanInvoke<Func, T...>;
1092 template <
typename Func,
typename... T>
1093 concept CanApplyTuple
1095 && requires (Func func, std::tuple<T...> wrapped_val) {
1096 { std::apply(func, std::get<0>(std::move(wrapped_val))) };
1099 template <
typename Func,
typename Return,
typename... T>
1100 concept InvokeReturns = requires (Func f, T... args) {
1101 { f(std::forward<T>(args)...) } -> std::same_as<Return>;
1105 template <
typename Func,
typename Return,
typename... T>
1106 concept ApplyReturns = InvokeReturns<Func, Return, T...>;
1108 template <
typename Func,
typename... T>
1109 concept InvokeReturnsAnyFuture = requires (Func f, T... args) {
1110 requires is_future<decltype(f(std::forward<T>(args)...))>::value;
1114 template <
typename Func,
typename... T>
1115 concept ApplyReturnsAnyFuture = InvokeReturnsAnyFuture<Func, T...>;
1122 template <typename T>
1123 using futurize_t =
typename futurize<T>::type;
1127 template<
typename Func,
typename... Args>
1128 auto futurize_invoke(Func&& func, Args&&... args) noexcept;
1130 template<
typename Func,
typename... Args>
1131 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept;
1135 namespace internal {
1138 promise_base* _promise;
1139 future_base() noexcept : _promise(
nullptr) {}
1140 future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
1141 _promise->_future =
this;
1142 _promise->_state = state;
1145 void move_it(future_base&& x, future_state_base* state) noexcept {
1146 _promise = x._promise;
1147 if (
auto* p = _promise) {
1154 future_base(future_base&& x, future_state_base* state) noexcept {
1155 move_it(std::move(x), state);
1158 void clear() noexcept {
1164 ~future_base() noexcept {
1168 promise_base* detach_promise() noexcept {
1169 _promise->_state =
nullptr;
1170 _promise->_future =
nullptr;
1171 return std::exchange(_promise,
nullptr);
1174 void schedule(task* tws, future_state_base* state) noexcept {
1175 promise_base* p = detach_promise();
1180 void do_wait() noexcept;
1182 #ifdef SEASTAR_COROUTINES_ENABLED
1183 void set_coroutine(task& coroutine) noexcept;
1186 friend class promise_base;
1189 template <
typename Func,
typename... T>
1190 struct future_result {
1191 using type = std::invoke_result_t<Func, T...>;
1192 using future_type = futurize_t<type>;
1193 using func_type = future_type (T&&...);
1196 template <
typename Func>
1197 struct future_result<Func, void> {
1198 using type = std::invoke_result_t<Func>;
1199 using future_type = futurize_t<type>;
1200 using func_type = future_type ();
1203 template <
typename Func,
typename SEASTAR_ELLIPSIS T>
1204 using future_result_t =
typename future_result<Func, T SEASTAR_ELLIPSIS>::type;
1206 template <
typename Func,
typename T>
1207 auto future_invoke(Func&& func, T&& v) {
1208 if constexpr (std::is_same_v<T, monostate>) {
1209 return std::invoke(std::forward<Func>(func));
1211 return std::invoke(std::forward<Func>(func), std::forward<T>(v));
1219 template <
typename Future>
1220 struct call_then_impl;
1224 template <
typename... T>
1225 struct call_then_impl<future<T...>> {
1226 template <
typename Func>
1227 using result_type =
typename future_result<Func, T...>::future_type;
1229 template <
typename Func>
1230 using func_type =
typename future_result<Func, T...>::func_type;
1232 template <
typename Func>
1233 static result_type<Func> run(future<T...>& fut, Func&& func) noexcept {
1234 return fut.then_impl(std::forward<Func>(func));
1238 #if SEASTAR_API_LEVEL < 4
1241 template <
typename... T>
1242 struct call_then_impl<future<when_all_succeed_tuple<T...>>> {
1243 template <
typename Func>
1244 using result_type = futurize_t<std::invoke_result_t<Func, T&&...>>;
1246 template <
typename Func>
1247 using func_type = result_type<Func> (T&&...);
1249 using was_tuple = when_all_succeed_tuple<T...>;
1250 using std_tuple = std::tuple<T...>;
1252 template <
typename Func>
1253 static auto run(future<was_tuple>& fut, Func&& func) noexcept {
1256 return fut.then_impl([func = std::forward<Func>(func)] (was_tuple&& t)
mutable {
1257 return std::apply(func,
static_cast<std_tuple&&
>(std::move(t)));
1264 template <
typename Func,
typename... Args>
1265 using call_then_impl_result_type =
typename call_then_impl<future<Args...>>::template result_type<Func>;
1268 template <typename Func, typename... Args>
1269 concept CanInvokeWhenAllSucceed = requires {
1270 typename call_then_impl_result_type<Func, Args...>;
1274 template <typename Func, typename... T>
1275 struct result_of_apply {
1279 template <
typename Func,
typename... T>
1280 struct result_of_apply<Func, std::tuple<T...>> : std::invoke_result<Func, T...> {
1284 template <
typename Func,
typename... T>
1285 using result_of_apply_t =
typename result_of_apply<Func, T...>::type;
1289 template <
typename Promise,
typename SEASTAR_ELLIPSIS T>
1290 task* continuation_base_with_promise<Promise, T SEASTAR_ELLIPSIS>::waiting_task() noexcept {
1291 return _pr.waiting_task();
1336 template <
typename SEASTAR_ELLIPSIS T>
1337 class SEASTAR_NODISCARD
future :
private internal::future_base {
1338 using future_state = seastar::future_state<internal::future_stored_type_t<T SEASTAR_ELLIPSIS>>;
1339 future_state _state;
1340 static constexpr
bool copy_noexcept = future_state::copy_noexcept;
1341 using call_then_impl = internal::call_then_impl<future>;
1353 template <
typename... A>
1360 [[gnu::always_inline]]
1361 explicit future(future_state&& state) noexcept
1362 : _state(std::move(state)) {
1364 internal::promise_base_with_type<T SEASTAR_ELLIPSIS> get_promise() noexcept {
1366 return internal::promise_base_with_type<T SEASTAR_ELLIPSIS>(
this);
1368 internal::promise_base_with_type<T SEASTAR_ELLIPSIS>* detach_promise() noexcept {
1369 return static_cast<internal::promise_base_with_type<T SEASTAR_ELLIPSIS>*
>(future_base::detach_promise());
1371 void schedule(continuation_base<T SEASTAR_ELLIPSIS>* tws) noexcept {
1372 future_base::schedule(tws, &tws->_state);
1374 template <
typename Pr,
typename Func,
typename Wrapper>
1375 void schedule(Pr&& pr, Func&& func, Wrapper&& wrapper) noexcept {
1381 auto tws =
new continuation<Pr, Func, Wrapper, T SEASTAR_ELLIPSIS>(std::move(pr), std::move(func), std::move(wrapper));
1384 #ifdef SEASTAR_DEBUG
1385 if (_state.available()) {
1386 tws->set_state(std::move(_state));
1387 ::seastar::schedule(tws);
1392 _state._u.st = future_state_base::state::invalid;
1395 [[gnu::always_inline]]
1396 future_state&& get_available_state_ref() noexcept {
1400 return std::move(_state);
1411 template<
typename... U>
1415 using value_type = internal::future_stored_type_t<T SEASTAR_ELLIPSIS>;
1416 using tuple_type = internal::future_tuple_type_t<value_type>;
1420 [[gnu::always_inline]]
1421 future(
future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1425 move_it(std::move(x), &_state);
1426 _state = std::move(x._state);
1429 void operator=(
const future&) =
delete;
1439 [[gnu::always_inline]]
1442 return get_available_state_ref().take();
1445 [[gnu::always_inline]]
1446 std::exception_ptr get_exception() noexcept {
1447 return get_available_state_ref().get_exception();
1460 #if SEASTAR_API_LEVEL < 5
1461 return future_state::get0(get());
1473 if (_state.available()) {
1482 [[gnu::always_inline]]
1484 return _state.available();
1490 [[gnu::always_inline]]
1492 return _state.failed();
1510 template <
typename Func,
typename Result = futurize_t<
typename call_then_impl::
template result_type<Func>>>
1511 SEASTAR_CONCEPT( requires std::invocable<Func, T SEASTAR_ELLIPSIS> || internal::CanInvokeWhenAllSucceed<Func, T SEASTAR_ELLIPSIS>)
1519 #ifndef SEASTAR_TYPE_ERASE_MORE
1520 return call_then_impl::run(*
this, std::move(func));
1522 using func_type =
typename call_then_impl::template func_type<Func>;
1527 return futurize_invoke(func, std::forward<decltype(args)>(args)...);
1530 return call_then_impl::run(*
this, std::move(ncf));
1553 template <
typename Func,
typename Result = futurize_t<
internal::result_of_apply_t<Func, T SEASTAR_ELLIPSIS>>>
1554 SEASTAR_CONCEPT( requires ::seastar::CanApplyTuple<Func, T SEASTAR_ELLIPSIS>)
1557 return then([func = std::forward<Func>(func)] (T&& SEASTAR_ELLIPSIS tuple)
mutable {
1559 return std::apply(func, std::move(tuple) SEASTAR_ELLIPSIS);
1566 template <
typename Func,
typename Result>
1567 Result then_impl_nrvo(Func&& func) noexcept {
1570 using pr_type = decltype(fut.get_promise());
1571 schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1572 if (state.failed()) {
1573 pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1575 futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1576 #if SEASTAR_API_LEVEL < 5
1577 return std::apply(func, std::move(state).get_value());
1582 return internal::future_invoke(func, std::move(state).get_value());
1590 template <
typename Func,
typename Result = futurize_t<
internal::future_result_t<Func, T SEASTAR_ELLIPSIS>>>
1592 then_impl(Func&& func) noexcept {
1593 #ifndef SEASTAR_DEBUG
1594 using futurator = futurize<internal::future_result_t<Func, T SEASTAR_ELLIPSIS>>;
1597 }
else if (available()) {
1598 #if SEASTAR_API_LEVEL < 5
1599 return futurator::apply(std::forward<Func>(func), get_available_state_ref().take_value());
1601 return futurator::invoke(std::forward<Func>(func), get_available_state_ref().take_value());
1605 return then_impl_nrvo<Func, Result>(std::forward<Func>(func));
1624 template <
typename Func,
typename FuncResult = std::invoke_result_t<Func, future>>
1625 SEASTAR_CONCEPT( requires std::invocable<Func, future> )
1626 futurize_t<FuncResult>
1628 return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1631 template <
typename Func,
typename FuncResult = std::invoke_result_t<Func, future&&>>
1632 SEASTAR_CONCEPT( requires std::invocable<Func, future&&> )
1633 futurize_t<FuncResult>
1634 then_wrapped(Func&& func) && noexcept {
1635 return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1640 template <
bool AsSelf,
typename FuncResult,
typename Func>
1641 futurize_t<FuncResult>
1642 then_wrapped_maybe_erase(Func&& func) noexcept {
1643 #ifndef SEASTAR_TYPE_ERASE_MORE
1644 return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1646 using futurator = futurize<FuncResult>;
1647 using WrapFuncResult =
typename futurator::type;
1648 noncopyable_function<WrapFuncResult (future&&)> ncf;
1650 memory::scoped_critical_alloc_section _;
1651 ncf = noncopyable_function<WrapFuncResult(future &&)>([func = std::forward<Func>(func)](future&& f)
mutable {
1652 return futurator::invoke(func, std::move(f));
1655 return then_wrapped_common<AsSelf, WrapFuncResult>(std::move(ncf));
1660 template <
typename FuncResult,
typename Func>
1661 futurize_t<FuncResult>
1662 then_wrapped_nrvo(Func&& func) noexcept {
1663 using futurator = futurize<FuncResult>;
1664 typename futurator::type fut(future_for_get_promise_marker{});
1665 using pr_type = decltype(fut.get_promise());
1666 schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1667 futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1668 return func(future(std::move(state)));
1675 template <
bool AsSelf,
typename FuncResult,
typename Func>
1676 futurize_t<FuncResult>
1677 then_wrapped_common(Func&& func) noexcept {
1678 #ifndef SEASTAR_DEBUG
1679 using futurator = futurize<FuncResult>;
1681 if constexpr (AsSelf) {
1685 return futurator::invoke(std::forward<Func>(func), std::move(*
this));
1687 return futurator::invoke(std::forward<Func>(func), future(get_available_state_ref()));
1691 return then_wrapped_nrvo<FuncResult, Func>(std::forward<Func>(func));
1694 void forward_to(internal::promise_base_with_type<T SEASTAR_ELLIPSIS>&& pr) noexcept {
1695 if (_state.available()) {
1696 pr.set_urgent_state(std::move(_state));
1698 *detach_promise() = std::move(pr);
1714 if (_state.available()) {
1715 pr.set_urgent_state(std::move(_state));
1716 }
else if (&pr._local_state != pr._state) {
1721 *detach_promise() = std::move(pr);
1742 template <
typename Func>
1743 SEASTAR_CONCEPT( requires std::invocable<Func> )
1744 future<T SEASTAR_ELLIPSIS> finally(Func&& func) noexcept {
1745 return then_wrapped(finally_body<Func,
is_future<std::invoke_result_t<Func>>::value>(std::forward<Func>(func)));
1749 template <
typename Func,
bool FuncReturnsFuture>
1752 template <
typename Func>
1756 finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1760 return futurize_invoke(_func).then_wrapped([result = std::move(result)](
auto&& f_res)
mutable {
1761 if (!f_res.failed()) {
1762 return std::move(result);
1764 return result.rethrow_with_nested(std::move(f_res._state));
1770 template <
typename Func>
1774 finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1780 return std::move(result);
1782 return result.rethrow_with_nested();
1792 return then_wrapped([] (
auto&& f) {
1796 engine_exit(std::current_exception());
1808 return then([] (
auto&&...) {});
1824 template <
typename Func>
1831 return then_wrapped([func = std::forward<Func>(func)]
1833 if (!fut.failed()) {
1834 return make_ready_future<T SEASTAR_ELLIPSIS>(fut.get());
1836 return futurize_invoke(func, fut.get_exception());
1851 template <
typename Func>
1854 static_assert(trait::arity == 1,
"func can take only one parameter");
1855 using ex_type =
typename trait::template arg<0>::type;
1856 return then_wrapped([func = std::forward<Func>(func)]
1859 return make_ready_future<T SEASTAR_ELLIPSIS>(fut.get());
1860 }
catch(ex_type& ex) {
1861 return futurize_invoke(func, ex);
1875 #ifdef SEASTAR_COROUTINES_ENABLED
1876 using future_base::set_coroutine;
1879 void set_callback(continuation_base<T SEASTAR_ELLIPSIS>* callback) noexcept {
1880 if (_state.available()) {
1881 callback->set_state(get_available_state_ref());
1882 ::seastar::schedule(callback);
1891 template <
typename SEASTAR_ELLIPSIS U>
1892 friend class future;
1893 template <
typename SEASTAR_ELLIPSIS U>
1894 friend class promise;
1895 template <
typename U>
1896 friend struct futurize;
1897 template <
typename SEASTAR_ELLIPSIS U>
1898 friend class internal::promise_base_with_type;
1899 template <
typename... U,
typename... A>
1901 template <
typename... U>
1903 template <
typename... U,
typename Exception>
1905 template <
typename... U>
1907 template <
typename... U>
1909 template <typename... U, typename V>
1910 friend
void internal::set_callback(future<U...>&, V*) noexcept;
1911 template <typename Future>
1912 friend struct internal::call_then_impl;
1917 namespace internal {
1918 template <
typename T>
1919 struct futurize_base {
1921 using type = future<T>;
1923 using promise_type = promise<T>;
1924 using promise_base_with_type = internal::promise_base_with_type<T>;
1927 static inline type convert(T&& value) {
return make_ready_future<T>(std::move(value)); }
1928 static inline type convert(type&& value) {
return std::move(value); }
1931 template <
typename Arg>
1936 struct futurize_base<void> {
1937 using type = future<>;
1938 using promise_type = promise<>;
1939 using promise_base_with_type = internal::promise_base_with_type<>;
1941 static inline type convert(type&& value) {
1942 return std::move(value);
1944 template <
typename Arg>
1948 template <
typename T>
1949 struct futurize_base<future<T>> :
public futurize_base<T> {};
1952 struct futurize_base<future<>> :
public futurize_base<void> {};
1955 template <
typename T>
1957 using base = internal::futurize_base<T>;
1960 using promise_base_with_type =
typename base::promise_base_with_type;
1963 using tuple_type =
typename type::tuple_type;
1964 using base::convert;
1969 template<
typename Func,
typename... FuncArgs>
1970 static inline type
apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
1974 template<
typename Func,
typename... FuncArgs>
1975 static inline type
invoke(Func&& func, FuncArgs&&... args) noexcept;
1977 template<
typename Func>
1978 static inline type
invoke(Func&& func, internal::monostate) noexcept {
1979 return invoke(std::forward<Func>(func));
1983 template<
typename Func,
typename... FuncArgs>
1984 [[deprecated(
"Use invoke for varargs")]]
1985 static inline type
apply(Func&& func, FuncArgs&&... args) noexcept {
1986 return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1989 static type current_exception_as_future() noexcept {
2002 #if SEASTAR_API_LEVEL >= 5
2016 template<
typename Func>
2017 SEASTAR_CONCEPT( requires std::invocable<Func> )
2018 static void satisfy_with_result_of(promise_base_with_type&&, Func&& func);
2020 template <
typename SEASTAR_ELLIPSIS U>
2024 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
2025 : _future(future), _state(state) {
2026 _future->_promise =
this;
2029 template <
typename SEASTAR_ELLIPSIS T>
2031 future<T SEASTAR_ELLIPSIS>
2033 assert(!this->_future && this->_state && !this->_task);
2037 template <
typename SEASTAR_ELLIPSIS T>
2040 if (this->_state == &x._local_state) {
2041 this->_state = &_local_state;
2042 new (&_local_state) future_state(std::move(x._local_state));
2046 template <
typename... T,
typename... A>
2052 template <
typename... T>
2058 template <
typename... T>
2061 return future<T...>(exception_future_marker(), std::move(state));
2064 template <
typename... T>
2069 void log_exception_trace() noexcept;
2077 template <typename... T, typename Exception>
2080 log_exception_trace();
2084 template <
typename... T,
typename Exception>
2085 future<T...> make_exception_future_with_backtrace(Exception&& ex) noexcept {
2086 return make_exception_future<T...>(make_backtraced_exception_ptr<Exception>(std::forward<Exception>(ex)));
2093 template<
typename T>
2094 template<
typename Func,
typename... FuncArgs>
2095 typename futurize<T>::type
futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
2097 using ret_t = decltype(std::apply(std::forward<Func>(func), std::move(args)));
2098 if constexpr (std::is_void_v<ret_t>) {
2099 std::apply(std::forward<Func>(func), std::move(args));
2100 return make_ready_future<>();
2101 }
else if constexpr (is_future<ret_t>::value){
2102 return std::apply(std::forward<Func>(func), std::move(args));
2104 return convert(std::apply(std::forward<Func>(func), std::move(args)));
2111 template<
typename T>
2112 template<
typename Func>
2113 SEASTAR_CONCEPT( requires std::invocable<Func> )
2114 void futurize<T>::satisfy_with_result_of(promise_base_with_type&& pr, Func&& func) {
2115 using ret_t = decltype(func());
2116 if constexpr (std::is_void_v<ret_t>) {
2119 }
else if constexpr (is_future<ret_t>::value) {
2120 func().forward_to(std::move(pr));
2122 pr.set_value(func());
2126 template<
typename T>
2127 template<
typename Func,
typename... FuncArgs>
2128 typename futurize<T>::type
futurize<T>::invoke(Func&& func, FuncArgs&&... args) noexcept {
2130 using ret_t = decltype(func(std::forward<FuncArgs>(args)...));
2131 if constexpr (std::is_void_v<ret_t>) {
2132 func(std::forward<FuncArgs>(args)...);
2133 return make_ready_future<>();
2134 }
else if constexpr (is_future<ret_t>::value) {
2135 return func(std::forward<FuncArgs>(args)...);
2137 return convert(func(std::forward<FuncArgs>(args)...));
2144 template <
typename T>
2145 template <
typename Arg>
2151 return make_exception_future<T>(std::forward<Arg>(arg));
2154 template <
typename Arg>
2160 return make_exception_future<>(std::forward<Arg>(arg));
2163 template<
typename Func,
typename... Args>
2164 auto futurize_invoke(Func&& func, Args&&... args) noexcept {
2165 using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2166 return futurator::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2169 template<
typename Func,
typename... Args>
2170 [[deprecated(
"Use futurize_invoke for varargs")]]
2171 auto futurize_apply(Func&& func, Args&&... args) noexcept {
2172 return futurize_invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2175 template<
typename Func,
typename... Args>
2176 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept {
2177 using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2178 return futurator::apply(std::forward<Func>(func), std::move(args));
2181 namespace internal {
2183 template <
typename... T,
typename U>
2185 void set_callback(future<T...>& fut, U* callback) noexcept {
2188 return fut.set_callback(callback);