24 #ifndef SEASTAR_MODULE
32 #include <type_traits>
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/concepts.hh>
42 #include <seastar/util/noncopyable_function.hh>
43 #include <seastar/util/backtrace.hh>
44 #include <seastar/util/std-compat.hh>
45 #include <seastar/util/modules.hh>
50 std::exception_ptr inner;
51 std::exception_ptr outer;
52 nested_exception(std::exception_ptr inner, std::exception_ptr outer) noexcept;
55 [[noreturn]]
void rethrow_nested()
const;
56 virtual const char* what()
const noexcept
override;
149 SEASTAR_MODULE_EXPORT_BEGIN
150 template <
class T =
void>
156 template <
typename... T>
167 template <
typename T = void,
typename... A>
176 template <
typename T =
void>
179 template <
typename T =
void,
typename Exception>
182 template <
typename T =
void>
184 return make_exception_future<T>(std::exception_ptr(ex));
187 template <
typename T =
void>
189 return make_exception_future<T>(
static_cast<const std::exception_ptr&
>(ex));
192 template <
typename T =
void>
195 return make_exception_future<T>(std::exception_ptr(ex));
197 SEASTAR_MODULE_EXPORT_END
199 void engine_exit(std::exception_ptr eptr = {});
201 void report_failed_future(
const std::exception_ptr& ex) noexcept;
203 void report_failed_future(
const future_state_base& state) noexcept;
213 SEASTAR_MODULE_EXPORT
223 SEASTAR_MODULE_EXPORT
224 template <
typename T =
void>
227 SEASTAR_MODULE_EXPORT
232 template <
class T =
void>
233 class promise_base_with_type;
238 template <
typename... T>
239 struct future_stored_type;
242 struct future_stored_type<> {
243 using type = monostate;
246 template <
typename T>
247 struct future_stored_type<T> {
248 using type = std::conditional_t<std::is_void_v<T>, internal::monostate, T>;
251 template <
typename... T>
252 using future_stored_type_t =
typename future_stored_type<T...>::type;
255 using future_tuple_type_t = std::conditional_t<std::is_same_v<T, monostate>, std::tuple<>, std::tuple<T>>;
259 template <
typename T>
260 struct get0_return_type;
263 struct get0_return_type<std::tuple<>> {
265 static type get0(std::tuple<>) { }
268 template <
typename T0,
typename... T>
269 struct get0_return_type<std::tuple<T0, T...>> {
271 static type get0(std::tuple<T0, T...> v) {
return std::get<0>(std::move(v)); }
275 using maybe_wrap_ref = std::conditional_t<std::is_reference_v<T>, std::reference_wrapper<std::remove_reference_t<T>>, T>;
284 template <
typename T,
bool is_trivial_
class>
285 struct uninitialized_wrapper_base;
287 template <
typename T>
288 struct uninitialized_wrapper_base<T, false> {
289 using tuple_type = future_tuple_type_t<T>;
294 maybe_wrap_ref<T> value;
298 uninitialized_wrapper_base() noexcept = default;
299 template<typename... U>
300 std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>,
void>
301 uninitialized_set(U&&... vs) {
302 new (&_v.value) maybe_wrap_ref<T>{T(std::forward<U>(vs)...)};
304 void uninitialized_set(tuple_type&& v) {
305 uninitialized_set(std::move(std::get<0>(v)));
307 void uninitialized_set(
const tuple_type& v) {
308 uninitialized_set(std::get<0>(v));
310 maybe_wrap_ref<T>& uninitialized_get() {
313 const maybe_wrap_ref<T>& uninitialized_get()
const {
318 template <
typename T>
struct uninitialized_wrapper_base<T, true> :
private T {
319 using tuple_type = future_tuple_type_t<T>;
320 uninitialized_wrapper_base() noexcept = default;
321 template<typename... U>
322 std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>,
void>
323 uninitialized_set(U&&... vs) {
324 new (
this) T(std::forward<U>(vs)...);
326 void uninitialized_set(tuple_type&& v) {
327 if constexpr (std::tuple_size_v<tuple_type> != 0) {
328 uninitialized_set(std::move(std::get<0>(v)));
331 void uninitialized_set(
const tuple_type& v) {
332 if constexpr (std::tuple_size_v<tuple_type> != 0) {
333 uninitialized_set(std::get<0>(v));
336 T& uninitialized_get() {
339 const T& uninitialized_get()
const {
344 template <
typename T>
345 constexpr
bool can_inherit =
346 (std::is_trivially_destructible_v<T> && std::is_trivially_constructible_v<T> &&
347 std::is_class_v<T> && !std::is_final_v<T>);
351 template <
typename T>
352 struct uninitialized_wrapper
353 :
public uninitialized_wrapper_base<T, can_inherit<T>> {};
355 template <
typename T>
356 struct is_trivially_move_constructible_and_destructible {
357 static constexpr
bool value = std::is_trivially_move_constructible_v<T> && std::is_trivially_destructible_v<T>;
361 struct all_true : std::false_type {};
364 struct all_true<> : std::true_type {};
367 struct all_true<true, v...> :
public all_true<v...> {};
370 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper;
372 template <
typename... T>
373 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper<std::tuple<T...>> {
374 static constexpr
bool value = all_true<is_trivially_move_constructible_and_destructible<T>::value...>::value;
377 template <
typename T>
378 static constexpr
bool is_tuple_effectively_trivially_move_constructible_and_destructible =
379 is_tuple_effectively_trivially_move_constructible_and_destructible_helper<T>::value;
410 SEASTAR_MODULE_EXPORT
412 static_assert(
sizeof(std::exception_ptr) ==
sizeof(
void*),
"exception_ptr not a pointer");
413 enum class state : uintptr_t {
423 result_unavailable = 2,
428 any() noexcept { st = state::future; }
429 any(state s) noexcept { st = s; }
430 void set_exception(std::exception_ptr&& e) noexcept {
431 new (&ex) std::exception_ptr(std::move(e));
432 assert(st >= state::exception_min);
434 any(std::exception_ptr&& e) noexcept {
435 set_exception(std::move(e));
438 bool valid()
const noexcept {
return st != state::invalid && st != state::result_unavailable; }
439 bool available()
const noexcept {
return st == state::result || st >= state::exception_min; }
440 bool failed()
const noexcept {
return __builtin_expect(st >= state::exception_min,
false); }
441 void check_failure() noexcept;
443 std::exception_ptr take_exception() noexcept {
444 std::exception_ptr ret(std::move(ex));
457 void move_it(
any&& x) noexcept {
466 memmove(
static_cast<void*
>(
this), &x,
sizeof(
any));
467 x.st = state::invalid;
469 if (x.st < state::exception_min) {
471 x.st = state::invalid;
473 new (&ex) std::exception_ptr(x.take_exception());
478 move_it(std::move(x));
480 any& operator=(
any&& x) noexcept {
485 move_it(std::move(x));
488 bool has_result()
const noexcept {
489 return st == state::result || st == state::result_unavailable;
492 std::exception_ptr ex;
498 future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
510 void rethrow_exception() &&;
511 void rethrow_exception() const&;
515 bool valid() const noexcept {
return _u.valid(); }
516 bool available() const noexcept {
return _u.available(); }
517 bool failed() const noexcept {
return _u.failed(); }
519 void ignore() noexcept;
521 void set_exception(std::exception_ptr&& ex) noexcept {
522 assert(_u.st == state::future);
523 _u.set_exception(std::move(ex));
525 future_state_base& operator=(future_state_base&& x) noexcept =
default;
526 void set_exception(future_state_base&& state) noexcept {
527 assert(_u.st == state::future);
528 *
this = std::move(state);
530 std::exception_ptr get_exception() && noexcept {
531 assert(_u.st >= state::exception_min);
533 return _u.take_exception();
535 const std::exception_ptr& get_exception() const& noexcept {
536 assert(_u.st >= state::exception_min);
539 template <
typename U>
540 friend struct future_state;
541 template <
typename U>
543 template <typename U>
545 template <typename T>
546 friend struct futurize;
549 void report_failed_future(future_state_base::any&& state) noexcept;
551 inline
void future_state_base::any::check_failure() noexcept {
553 report_failed_future(std::move(*
this));
562 template <
typename T>
563 struct future_state :
public future_state_base,
private internal::uninitialized_wrapper<T> {
564 static constexpr
bool copy_noexcept = std::is_nothrow_copy_constructible_v<T>;
565 static constexpr
bool has_trivial_move_and_destroy = internal::is_trivially_move_constructible_and_destructible<T>::value;
566 static_assert(std::is_nothrow_move_constructible_v<T>,
567 "Types must be no-throw move constructible");
568 static_assert(std::is_nothrow_destructible_v<T>,
569 "Types must be no-throw destructible");
570 future_state() noexcept = default;
571 void move_it(future_state&& x) noexcept {
572 if constexpr (has_trivial_move_and_destroy) {
573 #pragma GCC diagnostic push
578 #pragma GCC diagnostic ignored "-Wuninitialized"
579 memmove(
reinterpret_cast<char*
>(&this->uninitialized_get()),
580 &x.uninitialized_get(),
581 internal::used_size<internal::maybe_wrap_ref<T>>::value);
582 #pragma GCC diagnostic pop
583 }
else if (_u.has_result()) {
584 this->uninitialized_set(std::move(x.uninitialized_get()));
585 std::destroy_at(&x.uninitialized_get());
589 [[gnu::always_inline]]
590 future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
591 move_it(std::move(x));
594 void clear() noexcept {
595 if (_u.has_result()) {
596 std::destroy_at(&this->uninitialized_get());
601 __attribute__((always_inline))
602 ~future_state() noexcept {
605 future_state& operator=(future_state&& x) noexcept {
607 future_state_base::operator=(std::move(x));
610 move_it(std::move(x));
613 template <
typename... A>
614 future_state(ready_future_marker, A&&... a) noexcept : future_state_base(state::result) {
616 this->uninitialized_set(std::forward<A>(a)...);
618 new (
this) future_state(current_exception_future_marker());
621 template <
typename... A>
622 void set(A&&... a) noexcept {
623 assert(_u.st == state::future);
624 new (
this) future_state(ready_future_marker(), std::forward<A>(a)...);
626 future_state(exception_future_marker, std::exception_ptr&& ex) noexcept : future_state_base(std::move(ex)) { }
627 future_state(exception_future_marker, future_state_base&& state) noexcept : future_state_base(std::move(state)) { }
628 future_state(current_exception_future_marker m) noexcept : future_state_base(m) { }
629 future_state(nested_exception_marker m, future_state_base&& old) noexcept : future_state_base(m, std::move(old)) { }
630 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)) { }
631 T&& get_value() && noexcept {
632 assert(_u.st == state::result);
633 return static_cast<T&&
>(this->uninitialized_get());
635 T&& take_value() && noexcept {
636 assert(_u.st == state::result);
637 _u.st = state::result_unavailable;
638 return static_cast<T&&
>(this->uninitialized_get());
640 template<
typename U = T>
641 const std::enable_if_t<std::is_copy_constructible_v<U>, U>& get_value() const& noexcept(copy_noexcept) {
642 assert(_u.st == state::result);
643 return this->uninitialized_get();
647 if (_u.st >= state::exception_min) {
648 std::move(*this).rethrow_exception();
650 _u.st = state::result_unavailable;
651 return static_cast<T&&
>(this->uninitialized_get());
655 if (_u.st >= state::exception_min) {
656 std::move(*this).rethrow_exception();
658 return static_cast<T&&
>(this->uninitialized_get());
660 const T& get() const& {
662 if (_u.st >= state::exception_min) {
665 return this->uninitialized_get();
667 using get0_return_type =
typename internal::get0_return_type<internal::future_tuple_type_t<T>>::type;
668 static get0_return_type get0(T&& x) {
669 return internal::get0_return_type<T>::get0(std::move(x));
672 get0_return_type get0() {
673 return std::move(*this).get();
677 template <
typename T =
void>
678 class continuation_base :
public task {
680 using future_state = seastar::future_state<internal::future_stored_type_t<T>>;
682 using future_type = future<T>;
683 using promise_type = promise<T>;
685 continuation_base() noexcept = default;
686 void set_state(future_state&& state) noexcept {
687 _state = std::move(state);
693 virtual task* waiting_task() noexcept
override {
return nullptr; }
694 friend class internal::promise_base_with_type<T>;
695 friend class promise<T>;
696 friend class future<T>;
700 template <
typename Future>
701 struct continuation_base_from_future;
703 template <
typename... T>
704 struct continuation_base_from_future<future<T...>> {
705 using type = continuation_base<T...>;
708 template <
typename Future>
709 using continuation_base_from_future_t =
typename continuation_base_from_future<Future>::type;
711 template <
typename Promise,
typename T =
void>
712 class continuation_base_with_promise :
public continuation_base<T> {
713 friend class internal::promise_base_with_type<T>;
715 continuation_base_with_promise(Promise&& pr) noexcept : _pr(std::move(pr)) {
716 task::make_backtrace();
718 virtual task* waiting_task() noexcept override;
722 template <typename Promise, typename Func, typename Wrapper, typename T =
void>
723 struct continuation final : continuation_base_with_promise<Promise, T> {
734 continuation(Promise&& pr, Func&& func, Wrapper&& wrapper) noexcept
735 : continuation_base_with_promise<Promise, T>(std::move(pr))
736 , _func(std::move(func))
737 , _wrapper(std::move(wrapper)) {}
738 virtual void run_and_dispose() noexcept
override {
740 _wrapper(std::move(this->_pr), _func, std::move(this->_state));
742 this->_pr.set_to_current_exception();
747 [[no_unique_address]] Wrapper _wrapper;
752 template <
typename T =
void>
755 template <
typename... T,
typename U>
756 void set_callback(future<T...>&& fut, U* callback) noexcept;
762 enum class urgent { no, yes };
763 future_base* _future =
nullptr;
768 future_state_base* _state;
770 task* _task =
nullptr;
771 #ifdef SEASTAR_DEBUG_PROMISE
772 int _task_shard = -1;
774 void set_task(task* task) noexcept {
778 void assert_task_shard() const noexcept;
780 void set_task(task* task) noexcept {
783 void assert_task_shard() const noexcept { }
786 promise_base(
const promise_base&) =
delete;
787 promise_base(future_state_base* state) noexcept : _state(state) {}
788 promise_base(future_base* future, future_state_base* state) noexcept;
789 void move_it(promise_base&& x) noexcept;
790 promise_base(promise_base&& x) noexcept;
792 void clear() noexcept;
796 ~promise_base() noexcept {
800 void operator=(
const promise_base&) =
delete;
801 promise_base& operator=(promise_base&& x) noexcept;
803 template<urgent Urgent>
804 void make_ready() noexcept;
807 void set_exception_impl(T&& val) noexcept {
809 _state->set_exception(std::move(val));
810 make_ready<urgent::no>();
819 report_failed_future(val);
823 void set_exception(future_state_base&& state) noexcept {
824 set_exception_impl(std::move(state));
827 void set_exception(std::exception_ptr&& ex) noexcept {
828 set_exception_impl(std::move(ex));
831 void set_exception(
const std::exception_ptr& ex) noexcept {
832 set_exception(std::exception_ptr(ex));
835 template<
typename Exception>
836 std::enable_if_t<!std::is_same_v<std::remove_reference_t<Exception>, std::exception_ptr>,
void> set_exception(Exception&& e) noexcept {
837 set_exception(std::make_exception_ptr(std::forward<Exception>(e)));
840 friend class future_base;
848 void set_to_current_exception() noexcept;
851 task* waiting_task() const noexcept {
return _task; }
860 template <
typename T>
861 class promise_base_with_type :
protected internal::promise_base {
863 using future_state = seastar::future_state<future_stored_type_t<T>>;
864 future_state* get_state() noexcept {
865 return static_cast<future_state*
>(_state);
867 static constexpr
bool copy_noexcept = future_state::copy_noexcept;
869 promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
870 promise_base_with_type(future<T>* future) noexcept : promise_base(future, &future->_state) { }
871 promise_base_with_type(promise_base_with_type&& x) noexcept =
default;
872 promise_base_with_type(
const promise_base_with_type&) =
delete;
873 promise_base_with_type& operator=(promise_base_with_type&& x) noexcept =
default;
874 void operator=(
const promise_base_with_type&) =
delete;
876 void set_urgent_state(future_state&& state) noexcept {
877 auto* ptr = get_state();
884 assert(ptr->_u.st == future_state_base::state::future);
885 new (ptr) future_state(std::move(state));
886 make_ready<urgent::yes>();
890 template <
typename... A>
891 void set_value(A&&... a) noexcept {
892 if (
auto *s = get_state()) {
893 s->set(std::forward<A>(a)...);
894 make_ready<urgent::no>();
902 void set_to_current_exception() noexcept {
903 internal::promise_base::set_to_current_exception();
907 using internal::promise_base::waiting_task;
911 template <
typename U>
924 SEASTAR_MODULE_EXPORT
925 template <
typename T>
926 class promise :
private internal::promise_base_with_type<T> {
927 using future_state =
typename internal::promise_base_with_type<T>::future_state;
928 future_state _local_state;
934 promise() noexcept : internal::promise_base_with_type<T>(&_local_state) {}
938 promise(
promise&& x) noexcept : internal::promise_base_with_type<T>(std::move(x)) {
939 move_it(std::move(x));
943 internal::promise_base_with_type<T>::operator=(std::move(x));
946 move_it(std::move(x));
949 void operator=(
const promise&) =
delete;
956 internal::promise_base::set_to_current_exception();
960 using internal::promise_base::waiting_task;
981 template <typename... A>
982 void set_value(A&&... a) noexcept {
983 internal::promise_base_with_type<T>::set_value(std::forward<A>(a)...);
991 internal::promise_base::set_exception(std::move(ex));
994 void set_exception(
const std::exception_ptr& ex) noexcept {
995 internal::promise_base::set_exception(ex);
1002 template<
typename Exception>
1003 std::enable_if_t<!std::is_same_v<std::remove_reference_t<Exception>, std::exception_ptr>,
void>
set_exception(Exception&& e) noexcept {
1004 internal::promise_base::set_exception(std::forward<Exception>(e));
1007 using internal::promise_base_with_type<T>::set_urgent_state;
1009 template <
typename U>
1024 template <
typename... T>
struct is_future : std::false_type {};
1028 template <
typename... T>
struct is_future<
future<T...>> : std::true_type {};
1036 SEASTAR_MODULE_EXPORT
1037 template <
typename T>
1042 template <typename T>
1043 concept Future = is_future<T>::value;
1045 template <
typename Func,
typename... T>
1046 concept CanInvoke = std::invocable<Func, T...>;
1049 template <
typename Func,
typename... T>
1050 concept CanApply = CanInvoke<Func, T...>;
1052 template <
typename Func,
typename... T>
1053 concept CanApplyTuple
1055 && requires (Func func, std::tuple<T...> wrapped_val) {
1056 { std::apply(func, std::get<0>(std::move(wrapped_val))) };
1060 template <
typename Func,
typename Return,
typename... T>
1061 concept InvokeReturns = requires (Func f, T... args) {
1062 { f(std::forward<T>(args)...) } -> std::same_as<Return>;
1066 template <
typename Func,
typename Return,
typename... T>
1067 concept ApplyReturns = InvokeReturns<Func, Return, T...>;
1069 template <
typename Func,
typename... T>
1070 concept InvokeReturnsAnyFuture = Future<std::invoke_result_t<Func, T...>>;
1073 template <
typename Func,
typename... T>
1074 concept ApplyReturnsAnyFuture = InvokeReturnsAnyFuture<Func, T...>;
1081 template <typename T>
1082 using futurize_t =
typename futurize<T>::type;
1086 template<
typename Func,
typename... Args>
1087 auto futurize_invoke(Func&& func, Args&&... args) noexcept;
1089 template<
typename Func,
typename... Args>
1090 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept;
1094 namespace internal {
1097 promise_base* _promise;
1098 future_base() noexcept : _promise(
nullptr) {}
1099 future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
1100 _promise->_future =
this;
1101 _promise->_state = state;
1104 void move_it(future_base&& x, future_state_base* state) noexcept {
1105 _promise = x._promise;
1106 if (
auto* p = _promise) {
1113 future_base(future_base&& x, future_state_base* state) noexcept {
1114 move_it(std::move(x), state);
1117 void clear() noexcept {
1123 ~future_base() noexcept {
1127 promise_base* detach_promise() noexcept {
1128 _promise->_state =
nullptr;
1129 _promise->_future =
nullptr;
1130 return std::exchange(_promise,
nullptr);
1133 void schedule(task* tws, future_state_base* state) noexcept {
1134 promise_base* p = detach_promise();
1139 void do_wait() noexcept;
1141 #ifdef SEASTAR_COROUTINES_ENABLED
1142 void set_coroutine(task& coroutine) noexcept;
1145 friend class promise_base;
1148 template <
typename Func,
typename... T>
1149 struct future_result {
1150 using type = std::invoke_result_t<Func, T...>;
1151 using future_type = futurize_t<type>;
1152 using func_type = future_type (T&&...);
1155 template <
typename Func>
1156 struct future_result<Func, void> {
1157 using type = std::invoke_result_t<Func>;
1158 using future_type = futurize_t<type>;
1159 using func_type = future_type ();
1162 template <
typename Func,
typename T>
1163 using future_result_t =
typename future_result<Func, T>::type;
1165 template <
typename Func,
typename T>
1166 auto future_invoke(Func&& func, T&& v) {
1167 if constexpr (std::is_same_v<T, monostate>) {
1168 return std::invoke(std::forward<Func>(func));
1170 return std::invoke(std::forward<Func>(func), std::forward<T>(v));
1174 template <
typename Func,
typename... T>
1175 struct result_of_apply {
1179 template <
typename Func,
typename... T>
1180 struct result_of_apply<Func, std::tuple<T...>> : std::invoke_result<Func, T...> {
1184 template <
typename Func,
typename... T>
1185 using result_of_apply_t =
typename result_of_apply<Func, T...>::type;
1189 template <
typename Promise,
typename T>
1190 task* continuation_base_with_promise<Promise, T>::waiting_task() noexcept {
1191 return _pr.waiting_task();
1236 SEASTAR_MODULE_EXPORT
1237 template <
typename T>
1238 class [[nodiscard]]
future :
private internal::future_base {
1239 using future_state = seastar::future_state<internal::future_stored_type_t<T>>;
1240 future_state _state;
1241 static constexpr
bool copy_noexcept = future_state::copy_noexcept;
1252 future(
promise<T>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
1253 template <
typename... A>
1260 [[gnu::always_inline]]
1261 explicit future(future_state&& state) noexcept
1262 : _state(std::move(state)) {
1264 internal::promise_base_with_type<T> get_promise() noexcept {
1266 return internal::promise_base_with_type<T>(
this);
1268 internal::promise_base_with_type<T>* detach_promise() noexcept {
1269 return static_cast<internal::promise_base_with_type<T>*
>(future_base::detach_promise());
1271 void schedule(continuation_base<T>* tws) noexcept {
1272 future_base::schedule(tws, &tws->_state);
1274 template <
typename Pr,
typename Func,
typename Wrapper>
1275 void schedule(Pr&& pr, Func&& func, Wrapper&& wrapper) noexcept {
1281 auto tws =
new continuation<Pr, Func, Wrapper, T>(std::move(pr), std::move(func), std::move(wrapper));
1284 #ifdef SEASTAR_DEBUG
1285 if (_state.available()) {
1286 tws->set_state(get_available_state_ref());
1287 ::seastar::schedule(tws);
1292 _state._u.st = future_state_base::state::invalid;
1295 [[gnu::always_inline]]
1296 future_state&& get_available_state_ref() noexcept {
1300 return std::move(_state);
1307 future<T> rethrow_with_nested() noexcept {
1311 template<
typename... U>
1316 using tuple_type = internal::future_tuple_type_t<value_type>;
1320 [[gnu::always_inline]]
1321 future(
future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1325 move_it(std::move(x), &_state);
1326 _state = std::move(x._state);
1329 void operator=(
const future&) =
delete;
1339 [[gnu::always_inline]]
1342 return get_available_state_ref().take();
1345 [[gnu::always_inline]]
1346 std::exception_ptr get_exception() noexcept {
1347 return get_available_state_ref().get_exception();
1369 if (_state.available()) {
1378 [[gnu::always_inline]]
1380 return _state.available();
1386 [[gnu::always_inline]]
1388 return _state.failed();
1406 template <typename Func, typename Result = typename internal::future_result<Func, T>::future_type>
1407 SEASTAR_CONCEPT( requires std::invocable<Func, T>
1408 || (std::same_as<void, T> && std::invocable<Func>) )
1411 #ifndef SEASTAR_TYPE_ERASE_MORE
1412 return then_impl(std::move(func));
1414 using func_type =
typename internal::future_result<Func, T>::func_type;
1419 return futurize_invoke(func, std::forward<decltype(args)>(args)...);
1422 return then_impl(std::move(ncf));
1445 template <
typename Func,
typename Result = futurize_t<
internal::result_of_apply_t<Func, T>>>
1446 SEASTAR_CONCEPT( requires ::seastar::CanApplyTuple<Func, T>)
1449 return then([func = std::forward<Func>(func)] (T&& tuple)
mutable {
1451 return std::apply(func, std::move(tuple));
1458 template <
typename Func,
typename Result>
1459 Result then_impl_nrvo(Func&& func) noexcept {
1462 using pr_type = decltype(fut.get_promise());
1463 schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1464 if (state.failed()) {
1465 pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1467 futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1471 return internal::future_invoke(func, std::move(state).get_value());
1478 template <
typename Func,
typename Result = futurize_t<
internal::future_result_t<Func, T>>>
1480 then_impl(Func&& func) noexcept {
1481 #ifndef SEASTAR_DEBUG
1482 using futurator = futurize<internal::future_result_t<Func, T>>;
1484 return futurator::make_exception_future(
static_cast<future_state_base&&
>(get_available_state_ref()));
1485 }
else if (available()) {
1486 return futurator::invoke(std::forward<Func>(func), get_available_state_ref().take_value());
1489 return then_impl_nrvo<Func, Result>(std::forward<Func>(func));
1508 template <
typename Func,
typename FuncResult = std::invoke_result_t<Func, future>>
1509 SEASTAR_CONCEPT( requires std::invocable<Func, future> )
1510 futurize_t<FuncResult>
1512 return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1515 template <
typename Func,
typename FuncResult = std::invoke_result_t<Func, future&&>>
1516 SEASTAR_CONCEPT( requires std::invocable<Func, future&&> )
1517 futurize_t<FuncResult>
1518 then_wrapped(Func&& func) && noexcept {
1519 return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1524 template <
bool AsSelf,
typename FuncResult,
typename Func>
1525 futurize_t<FuncResult>
1526 then_wrapped_maybe_erase(Func&& func) noexcept {
1527 #ifndef SEASTAR_TYPE_ERASE_MORE
1528 return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1530 using futurator = futurize<FuncResult>;
1531 using WrapFuncResult =
typename futurator::type;
1532 noncopyable_function<WrapFuncResult (future&&)> ncf;
1534 memory::scoped_critical_alloc_section _;
1535 ncf = noncopyable_function<WrapFuncResult(future &&)>([func = std::forward<Func>(func)](future&& f)
mutable {
1536 return futurator::invoke(func, std::move(f));
1539 return then_wrapped_common<AsSelf, WrapFuncResult>(std::move(ncf));
1544 template <
typename FuncResult,
typename Func>
1545 futurize_t<FuncResult>
1546 then_wrapped_nrvo(Func&& func) noexcept {
1547 using futurator = futurize<FuncResult>;
1548 typename futurator::type fut(future_for_get_promise_marker{});
1549 using pr_type = decltype(fut.get_promise());
1550 schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1551 futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1552 return func(future(std::move(state)));
1559 template <
bool AsSelf,
typename FuncResult,
typename Func>
1560 futurize_t<FuncResult>
1561 then_wrapped_common(Func&& func) noexcept {
1562 #ifndef SEASTAR_DEBUG
1563 using futurator = futurize<FuncResult>;
1565 if constexpr (AsSelf) {
1569 return futurator::invoke(std::forward<Func>(func), std::move(*
this));
1571 return futurator::invoke(std::forward<Func>(func), future(get_available_state_ref()));
1575 return then_wrapped_nrvo<FuncResult, Func>(std::forward<Func>(func));
1578 void forward_to(internal::promise_base_with_type<T>&& pr) noexcept {
1579 if (_state.available()) {
1580 pr.set_urgent_state(std::move(_state));
1582 *detach_promise() = std::move(pr);
1598 if (_state.available()) {
1599 pr.set_urgent_state(std::move(_state));
1600 }
else if (&pr._local_state != pr._state) {
1605 *detach_promise() = std::move(pr);
1626 template <
typename Func>
1627 SEASTAR_CONCEPT( requires std::invocable<Func> )
1629 return then_wrapped(
finally_body<Func,
is_future<std::invoke_result_t<Func>>::value>(std::forward<Func>(func)));
1633 template <
typename Func,
bool FuncReturnsFuture>
1636 template <
typename Func>
1640 finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1644 return futurize_invoke(_func).then_wrapped([result = std::move(result)](
auto&& f_res)
mutable {
1645 if (!f_res.failed()) {
1646 return std::move(result);
1648 return result.rethrow_with_nested(std::move(f_res._state));
1654 template <
typename Func>
1658 finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1664 return std::move(result);
1666 return result.rethrow_with_nested();
1676 return then_wrapped([] (
auto&& f) {
1680 engine_exit(std::current_exception());
1692 return then([] (
auto&&...) {});
1708 template <
typename Func>
1709 SEASTAR_CONCEPT( requires std::is_invocable_r_v<
future<T> ,Func, std::exception_ptr>
1710 || (std::tuple_size_v<tuple_type> == 0 && std::is_invocable_r_v<void, Func, std::exception_ptr>)
1711 || (std::tuple_size_v<tuple_type> == 1 && std::is_invocable_r_v<T, Func, std::exception_ptr>)
1712 || (std::tuple_size_v<tuple_type> > 1 && std::is_invocable_r_v<tuple_type ,Func, std::exception_ptr>)
1714 future<T> handle_exception(Func&& func) noexcept {
1715 return then_wrapped([func = std::forward<Func>(func)]
1717 if (!fut.failed()) {
1718 return make_ready_future<T>(fut.get());
1720 return futurize_invoke(func, fut.get_exception());
1735 template <
typename Func>
1738 static_assert(trait::arity == 1,
"func can take only one parameter");
1739 using ex_type =
typename trait::template arg<0>::type;
1740 return then_wrapped([func = std::forward<Func>(func)]
1743 return make_ready_future<T>(fut.get());
1744 }
catch(ex_type& ex) {
1745 return futurize_invoke(func, ex);
1759 #ifdef SEASTAR_COROUTINES_ENABLED
1760 using future_base::set_coroutine;
1763 void set_task(
task& t) noexcept {
1765 _promise->set_task(&t);
1768 void set_callback(continuation_base<T>* callback) noexcept {
1769 if (_state.available()) {
1770 callback->set_state(get_available_state_ref());
1771 ::seastar::schedule(callback);
1780 template <
typename U>
1781 friend class future;
1782 template <
typename U>
1783 friend class promise;
1784 template <
typename U>
1785 friend struct futurize;
1786 template <
typename U>
1787 friend class internal::promise_base_with_type;
1788 template <
typename U,
typename... A>
1790 template <
typename U>
1792 template <
typename U,
typename Exception>
1794 template <
typename U>
1795 friend future<U> internal::make_exception_future(future_state_base&& state) noexcept;
1796 template <
typename U>
1798 template <typename... U, typename V>
1799 friend
void internal::set_callback(future<U...>&&, V*) noexcept;
1804 namespace internal {
1805 template <
typename T>
1806 struct futurize_base {
1808 using type = future<T>;
1810 using promise_type = promise<T>;
1811 using promise_base_with_type = internal::promise_base_with_type<T>;
1814 static inline type convert(T&& value) {
return make_ready_future<T>(std::move(value)); }
1815 static inline type convert(type&& value) {
return std::move(value); }
1818 template <
typename Arg>
1823 struct futurize_base<void> {
1826 using promise_base_with_type = internal::promise_base_with_type<>;
1828 static inline type convert(type&& value) {
1829 return std::move(value);
1831 template <
typename Arg>
1835 template <
typename T>
1836 struct futurize_base<future<T>> :
public futurize_base<T> {};
1839 struct futurize_base<future<>> :
public futurize_base<void> {};
1842 template <
typename T>
1844 using base = internal::futurize_base<T>;
1847 using promise_base_with_type =
typename base::promise_base_with_type;
1850 using tuple_type =
typename type::tuple_type;
1851 using base::convert;
1852 using base::make_exception_future;
1856 template<
typename Func,
typename... FuncArgs>
1857 static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
1861 template<
typename Func,
typename... FuncArgs>
1862 static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
1864 template<
typename Func>
1865 static inline type invoke(Func&& func, internal::monostate) noexcept {
1866 return invoke(std::forward<Func>(func));
1870 template<
typename Func,
typename... FuncArgs>
1871 [[deprecated(
"Use invoke for varargs")]]
1872 static inline type apply(Func&& func, FuncArgs&&... args) noexcept {
1873 return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1876 static type current_exception_as_future() noexcept {
1901 template<
typename Func>
1902 SEASTAR_CONCEPT( requires std::invocable<Func> )
1903 static void satisfy_with_result_of(promise_base_with_type&&, Func&& func);
1905 template <
typename U>
1909 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1910 : _future(future), _state(state) {
1911 _future->_promise =
this;
1914 template <
typename T>
1918 assert(!this->_future && this->_state && !this->_task);
1922 template <
typename T>
1925 if (this->_state == &x._local_state) {
1926 this->_state = &_local_state;
1927 new (&_local_state) future_state(std::move(x._local_state));
1931 SEASTAR_MODULE_EXPORT_BEGIN
1932 template <
typename T,
typename... A>
1938 template <
typename T>
1943 SEASTAR_MODULE_EXPORT_END
1945 template <
typename T>
1947 future<T> internal::make_exception_future(future_state_base&& state) noexcept {
1948 return future<T>(exception_future_marker(), std::move(state));
1951 SEASTAR_MODULE_EXPORT_BEGIN
1952 template <
typename T>
1957 void log_exception_trace() noexcept;
1965 template <typename T, typename Exception>
1968 log_exception_trace();
1969 return make_exception_future<T>(std::make_exception_ptr(std::forward<Exception>(ex)));
1972 template <
typename T,
typename Exception>
1973 future<T> make_exception_future_with_backtrace(Exception&& ex) noexcept {
1974 return make_exception_future<T>(make_backtraced_exception_ptr<Exception>(std::forward<Exception>(ex)));
1976 SEASTAR_MODULE_EXPORT_END
1982 template<
typename T>
1983 template<
typename Func,
typename... FuncArgs>
1984 typename futurize<T>::type
futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1986 using ret_t = decltype(std::apply(std::forward<Func>(func), std::move(args)));
1987 if constexpr (std::is_void_v<ret_t>) {
1988 std::apply(std::forward<Func>(func), std::move(args));
1989 return make_ready_future<>();
1990 }
else if constexpr (is_future<ret_t>::value){
1991 return std::apply(std::forward<Func>(func), std::move(args));
1993 return convert(std::apply(std::forward<Func>(func), std::move(args)));
2000 template<
typename T>
2001 template<
typename Func>
2002 SEASTAR_CONCEPT( requires std::invocable<Func> )
2003 void futurize<T>::satisfy_with_result_of(promise_base_with_type&& pr, Func&& func) {
2004 using ret_t = decltype(func());
2005 if constexpr (std::is_void_v<ret_t>) {
2008 }
else if constexpr (is_future<ret_t>::value) {
2009 func().forward_to(std::move(pr));
2015 template<
typename T>
2016 template<
typename Func,
typename... FuncArgs>
2017 typename futurize<T>::type
futurize<T>::invoke(Func&& func, FuncArgs&&... args) noexcept {
2019 using ret_t = decltype(func(std::forward<FuncArgs>(args)...));
2020 if constexpr (std::is_void_v<ret_t>) {
2021 func(std::forward<FuncArgs>(args)...);
2022 return make_ready_future<>();
2023 }
else if constexpr (is_future<ret_t>::value) {
2024 return func(std::forward<FuncArgs>(args)...);
2026 return convert(func(std::forward<FuncArgs>(args)...));
2033 template <
typename T>
2034 template <
typename Arg>
2037 internal::futurize_base<T>::make_exception_future(Arg&& arg) noexcept {
2038 using ::seastar::make_exception_future;
2039 using ::seastar::internal::make_exception_future;
2040 return make_exception_future<T>(std::forward<Arg>(arg));
2043 template <
typename Arg>
2046 internal::futurize_base<void>::make_exception_future(Arg&& arg) noexcept {
2047 using ::seastar::make_exception_future;
2048 using ::seastar::internal::make_exception_future;
2049 return make_exception_future<>(std::forward<Arg>(arg));
2052 template<
typename Func,
typename... Args>
2053 auto futurize_invoke(Func&& func, Args&&... args) noexcept {
2054 using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2055 return futurator::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2058 template<
typename Func,
typename... Args>
2059 [[deprecated(
"Use futurize_invoke for varargs")]]
2060 auto futurize_apply(Func&& func, Args&&... args) noexcept {
2061 return futurize_invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2064 template<
typename Func,
typename... Args>
2065 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept {
2066 using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2067 return futurator::apply(std::forward<Func>(func), std::move(args));
2070 namespace internal {
2072 template <
typename... T,
typename U>
2074 void set_callback(future<T...>&& fut, U* callback) noexcept {
2077 return std::move(fut).set_callback(callback);
A representation of a possibly not-yet-computed value.
Definition: future.hh:1238
void wait() noexcept
Definition: future.hh:1368
internal::future_stored_type_t< T > value_type
The data type carried by the future.
Definition: future.hh:1315
Result then(Func &&func) noexcept
Schedule a block of code to run when the future is ready.
Definition: future.hh:1410
bool failed() const noexcept
Checks whether the future has failed.
Definition: future.hh:1387
bool available() const noexcept
Checks whether the future is available.
Definition: future.hh:1379
typename future_state::get0_return_type get0_return_type
Definition: future.hh:1358
void forward_to(promise< T > &&pr) noexcept
Satisfy some promise object with this future as a result.
Definition: future.hh:1597
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:1511
Result then_unpack(Func &&func) noexcept
Schedule a block of code to run when the future is ready, unpacking tuples.
Definition: future.hh:1448
future(future &&x) noexcept
Moves the future into a new object.
Definition: future.hh:1321
value_type && get()
gets the value returned by the computation
Definition: future.hh:1340
future< T > handle_exception_type(Func &&func) noexcept
Handle the exception of a certain type carried by this future.
Definition: future.hh:1736
future discard_result() noexcept
Discards the value carried by this future.
Definition: future.hh:1689
future or_terminate() noexcept
Terminate the program if this future fails.
Definition: future.hh:1675
void ignore_ready_future() noexcept
Ignore any result hold by this future.
Definition: future.hh:1755
Definition: future.hh:1634
promise - allows a future value to be made available at a later time.
Definition: future.hh:926
void set_to_current_exception() noexcept
Definition: future.hh:955
void set_value(A &&... a) noexcept
Sets the promises value.
Definition: future.hh:982
void set_exception(std::exception_ptr &&ex) noexcept
Marks the promise as failed.
Definition: future.hh:990
promise() noexcept
Constructs an empty promise.
Definition: future.hh:934
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:1003
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:1934
future< T > get_future() noexcept
Gets the promise's associated future.
Definition: future.hh:1917
future< T > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1940
future< T > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:1953
void move_it(promise &&x) noexcept
Moves a promise object.
Definition: future.hh:1924
Definition: future.hh:558
Definition: future.hh:559
Definition: future.hh:557
Definition: critical_alloc_section.hh:80
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
SEASTAR_MODULE_EXPORT_BEGIN shard_id this_shard_id() noexcept
Returns shard_id of the of the current shard.
Definition: shard_id.hh:50
Definition: noncopyable_function.hh:37
Definition: function_traits.hh:62
Exception type for broken promises.
Definition: future.hh:214
Definition: future.hh:411
friend future< U > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:1953
Definition: future.hh:503
Definition: future.hh:505
Converts a type to a future type, if it isn't already.
Definition: future.hh:1843
static type apply(Func &&func, FuncArgs &&... args) noexcept
Deprecated alias of invoke.
Definition: future.hh:1872
static type from_tuple(tuple_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:1881
static type from_tuple(value_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:1890
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:1894
static type from_tuple(const tuple_type &value)
Convert the tuple representation into a future.
Definition: future.hh:1885
typename type::value_type value_type
The value tuple type associated with type.
Definition: future.hh:1849
static type invoke(Func &&func, FuncArgs &&... args) noexcept
Check whether a type is a future.
Definition: future.hh:1024
Definition: future.hh:427