2 * This file is open source software, licensed to you under the terms
3 * of the Apache License, Version 2.0 (the "License"). See the NOTICE file
4 * distributed with this work for additional information regarding copyright
5 * ownership. You may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing,
12 * software distributed under the License is distributed on an
13 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14 * KIND, either express or implied. See the License for the
15 * specific language governing permissions and limitations
19 * Copyright (C) 2015 Cloudius Systems, Ltd.
24 #include <seastar/core/apply.hh>
25 #include <seastar/core/task.hh>
26 #include <seastar/core/preempt.hh>
27 #include <seastar/core/thread_impl.hh>
31 #include <type_traits>
34 #include <seastar/core/function_traits.hh>
35 #include <seastar/util/alloc_failure_injector.hh>
36 #include <seastar/util/attribute-compat.hh>
37 #include <seastar/util/gcc6-concepts.hh>
38 #include <seastar/util/noncopyable_function.hh>
42 /// \defgroup future-module Futures and Promises
45 /// Futures and promises are the basic tools for asynchronous
46 /// programming in seastar. A future represents a result that
47 /// may not have been computed yet, for example a buffer that
48 /// is being read from the disk, or the result of a function
49 /// that is executed on another cpu. A promise object allows
50 /// the future to be eventually resolved by assigning it a value.
53 /// Another way to look at futures and promises are as the reader
54 /// and writer sides, respectively, of a single-item, single use
55 /// queue. You read from the future, and write to the promise,
56 /// and the system takes care that it works no matter what the
57 /// order of operations is.
60 /// The normal way of working with futures is to chain continuations
61 /// to them. A continuation is a block of code (usually a lamdba)
62 /// that is called when the future is assigned a value (the future
63 /// is resolved); the continuation can then access the actual value.
66 /// \defgroup future-util Future Utilities
69 /// These utilities are provided to help perform operations on futures.
72 /// \addtogroup future-module
81 template <typename... T>
84 struct future_state_base;
86 /// \brief Creates a \ref future in an available, value state.
88 /// Creates a \ref future object that is already resolved. This
89 /// is useful when it is determined that no I/O needs to be performed
90 /// to perform a computation (for example, because the data is cached
92 template <typename... T, typename... A>
93 future<T...> make_ready_future(A&&... value);
95 /// \brief Creates a \ref future in an available, failed state.
97 /// Creates a \ref future object that is already resolved in a failed
98 /// state. This is useful when no I/O needs to be performed to perform
99 /// a computation (for example, because the connection is closed and
100 /// we cannot read from it).
101 template <typename... T>
102 future<T...> make_exception_future(std::exception_ptr&& value) noexcept;
104 template <typename... T>
105 future<T...> make_exception_future(const std::exception_ptr& ex) noexcept {
106 return make_exception_future<T...>(std::exception_ptr(ex));
109 template <typename... T>
110 future<T...> make_exception_future(std::exception_ptr& ex) noexcept {
111 return make_exception_future<T...>(static_cast<const std::exception_ptr&>(ex));
115 void engine_exit(std::exception_ptr eptr = {});
117 void report_failed_future(const std::exception_ptr& ex) noexcept;
119 void report_failed_future(const future_state_base& state) noexcept;
123 /// \brief Exception type for broken promises
125 /// When a promise is broken, i.e. a promise object with an attached
126 /// continuation is destroyed before setting any value or exception, an
127 /// exception of `broken_promise` type is propagated to that abandoned
129 struct broken_promise : std::logic_error {
134 template <class... T>
135 class promise_base_with_type;
137 template <typename... T>
138 future<T...> current_exception_as_future() noexcept;
141 future<> current_exception_as_future() noexcept;
143 // It doesn't seem to be possible to use std::tuple_element_t with an empty tuple. There is an static_assert in it that
144 // fails the build even if it is in the non enabled side of std::conditional.
145 template <typename... T>
146 struct get0_return_type {
148 static type get0(std::tuple<T...> v) { }
151 template <typename T0, typename... T>
152 struct get0_return_type<T0, T...> {
154 static type get0(std::tuple<T0, T...> v) { return std::get<0>(std::move(v)); }
157 /// \brief Wrapper for keeping uninitialized values of non default constructible types.
159 /// This is similar to a std::optional<T>, but it doesn't know if it is holding a value or not, so the user is
160 /// responsible for calling constructors and destructors.
162 /// The advantage over just using a union directly is that this uses inheritance when possible and so benefits from the
163 /// empty base optimization.
164 template <typename T, bool is_trivial_class>
165 struct uninitialized_wrapper_base;
167 template <typename T>
168 struct uninitialized_wrapper_base<T, false> {
176 void uninitialized_set(T&& v) {
177 new (&_v.value) T(std::move(v));
179 T& uninitialized_get() {
182 const T& uninitialized_get() const {
187 template <typename T> struct uninitialized_wrapper_base<T, true> : private T {
188 void uninitialized_set(T&& v) {
189 new (this) T(std::move(v));
191 T& uninitialized_get() {
194 const T& uninitialized_get() const {
199 template <typename T>
200 constexpr bool can_inherit =
201 #ifdef _LIBCPP_VERSION
202 // We expect std::tuple<> to be trivially constructible and
203 // destructible. That is not the case with libc++
204 // (https://bugs.llvm.org/show_bug.cgi?id=41714). We could avoid this
205 // optimization when using libc++ and relax the asserts, but
206 // inspection suggests that std::tuple<> is trivial, it is just not
208 std::is_same<std::tuple<>, T>::value ||
210 (std::is_trivially_destructible<T>::value && std::is_trivially_constructible<T>::value &&
211 std::is_class<T>::value && !std::is_final<T>::value);
213 // The objective is to avoid extra space for empty types like std::tuple<>. We could use std::is_empty_v, but it is
214 // better to check that both the constructor and destructor can be skipped.
215 template <typename T>
216 struct uninitialized_wrapper
217 : public uninitialized_wrapper_base<T, can_inherit<T>> {};
219 static_assert(std::is_empty<uninitialized_wrapper<std::tuple<>>>::value, "This should still be empty");
221 template <typename T>
222 struct is_trivially_move_constructible_and_destructible {
223 static constexpr bool value = std::is_trivially_move_constructible<T>::value && std::is_trivially_destructible<T>::value;
227 struct all_true : std::false_type {};
230 struct all_true<> : std::true_type {};
233 struct all_true<true, v...> : public all_true<v...> {};
237 // A future/promise pair maintain one logical value (a future_state).
238 // There are up to three places that can store it, but only one is
239 // active at any time.
241 // - in the promise _local_state member variable
243 // This is necessary because a promise is created first and there
244 // would be nowhere else to put the value.
246 // - in the future _state variable
248 // This is used anytime a future exists and then has not been called
249 // yet. This guarantees a simple access to the value for any code
250 // that already has a future.
252 // - in the task associated with the .then() clause (after .then() is called,
253 // if a value was not set)
256 // The promise maintains a pointer to the state, which is modified as
257 // the state moves to a new location due to events (such as .then() or
258 // get_future being called) or due to the promise or future being
262 // non templated base class to reduce code duplication
263 struct future_state_base {
264 static_assert(std::is_nothrow_copy_constructible<std::exception_ptr>::value,
265 "std::exception_ptr's copy constructor must not throw");
266 static_assert(std::is_nothrow_move_constructible<std::exception_ptr>::value,
267 "std::exception_ptr's move constructor must not throw");
268 static_assert(sizeof(std::exception_ptr) == sizeof(void*), "exception_ptr not a pointer");
269 enum class state : uintptr_t {
272 // the substate is intended to decouple the run-time prevention
273 // for duplicative result extraction (calling e.g. then() twice
274 // ends up in abandoned()) from the wrapped object's destruction
275 // handling which is orchestrated by future_state. Instead of
276 // creating a temporary future_state just for the sake of setting
277 // the "invalid" in the source instance, result_unavailable can
278 // be set to ensure future_state_base::available() returns false.
279 result_unavailable = 2,
281 exception_min = 4, // or anything greater
284 any() { st = state::future; }
285 any(state s) { st = s; }
286 void set_exception(std::exception_ptr&& e) {
287 new (&ex) std::exception_ptr(std::move(e));
288 assert(st >= state::exception_min);
290 any(std::exception_ptr&& e) {
291 set_exception(std::move(e));
294 std::exception_ptr take_exception() {
295 std::exception_ptr ret(std::move(ex));
296 // Unfortunately in libstdc++ ~exception_ptr is defined out of line. We know that it does nothing for
297 // moved out values, so we omit calling it. This is critical for the code quality produced for this
298 // function. Without the out of line call, gcc can figure out that both sides of the if produce
299 // identical code and merges them.if
300 // We don't make any assumptions about other c++ libraries.
301 // There is request with gcc to define it inline: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90295
309 if (x.st < state::exception_min) {
311 x.st = state::invalid;
313 new (&ex) std::exception_ptr(x.take_exception());
316 bool has_result() const {
317 return st == state::result || st == state::result_unavailable;
320 std::exception_ptr ex;
323 future_state_base() noexcept { }
324 future_state_base(state st) noexcept : _u(st) { }
325 future_state_base(std::exception_ptr&& ex) noexcept : _u(std::move(ex)) { }
326 future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
328 // We never need to destruct this polymorphicly, so we can make it
329 // protected instead of virtual.
331 ~future_state_base() noexcept {
333 report_failed_future(_u.take_exception());
339 bool valid() const noexcept { return _u.st != state::invalid; }
340 bool available() const noexcept { return _u.st == state::result || _u.st >= state::exception_min; }
341 bool failed() const noexcept { return __builtin_expect(_u.st >= state::exception_min, false); }
343 void set_to_broken_promise() noexcept;
345 void ignore() noexcept {
349 assert(0 && "invalid state for ignore");
350 case state::result_unavailable:
352 _u.st = state::result_unavailable;
355 // Ignore the exception
360 void set_exception(std::exception_ptr&& ex) noexcept {
361 assert(_u.st == state::future);
362 _u.set_exception(std::move(ex));
364 future_state_base& operator=(future_state_base&& x) noexcept {
365 this->~future_state_base();
366 new (this) future_state_base(std::move(x));
369 void set_exception(future_state_base&& state) noexcept {
370 assert(_u.st == state::future);
371 *this = std::move(state);
373 std::exception_ptr get_exception() && noexcept {
374 assert(_u.st >= state::exception_min);
375 // Move ex out so future::~future() knows we've handled it
376 return _u.take_exception();
378 const std::exception_ptr& get_exception() const& noexcept {
379 assert(_u.st >= state::exception_min);
383 static future_state_base current_exception();
385 template <typename... U>
386 friend future<U...> internal::current_exception_as_future() noexcept;
389 struct ready_future_marker {};
390 struct exception_future_marker {};
391 struct future_for_get_promise_marker {};
394 template <typename... T>
395 struct future_state : public future_state_base, private internal::uninitialized_wrapper<std::tuple<T...>> {
396 static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible<std::tuple<T...>>::value;
397 static constexpr bool has_trivial_move_and_destroy =
398 internal::all_true<internal::is_trivially_move_constructible_and_destructible<T>::value...>::value;
399 static_assert(std::is_nothrow_move_constructible<std::tuple<T...>>::value,
400 "Types must be no-throw move constructible");
401 static_assert(std::is_nothrow_destructible<std::tuple<T...>>::value,
402 "Types must be no-throw destructible");
403 future_state() noexcept {}
404 [[gnu::always_inline]]
405 future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
406 if (has_trivial_move_and_destroy) {
407 memcpy(reinterpret_cast<char*>(&this->uninitialized_get()),
408 &x.uninitialized_get(),
409 internal::used_size<std::tuple<T...>>::value);
410 } else if (_u.has_result()) {
411 this->uninitialized_set(std::move(x.uninitialized_get()));
412 x.uninitialized_get().~tuple();
415 __attribute__((always_inline))
416 ~future_state() noexcept {
417 if (_u.has_result()) {
418 this->uninitialized_get().~tuple();
421 future_state& operator=(future_state&& x) noexcept {
422 this->~future_state();
423 new (this) future_state(std::move(x));
426 template <typename... A>
427 future_state(ready_future_marker, A&&... a) : future_state_base(state::result) {
428 this->uninitialized_set(std::tuple<T...>(std::forward<A>(a)...));
430 template <typename... A>
432 assert(_u.st == state::future);
433 new (this) future_state(ready_future_marker(), std::forward<A>(a)...);
435 future_state(exception_future_marker m, std::exception_ptr&& ex) : future_state_base(std::move(ex)) { }
436 future_state(exception_future_marker m, future_state_base&& state) : future_state_base(std::move(state)) { }
437 std::tuple<T...>&& get_value() && noexcept {
438 assert(_u.st == state::result);
439 return std::move(this->uninitialized_get());
441 std::tuple<T...>&& take_value() && noexcept {
442 assert(_u.st == state::result);
443 _u.st = state::result_unavailable;
444 return std::move(this->uninitialized_get());
446 template<typename U = std::tuple<T...>>
447 const std::enable_if_t<std::is_copy_constructible<U>::value, U>& get_value() const& noexcept(copy_noexcept) {
448 assert(_u.st == state::result);
449 return this->uninitialized_get();
451 std::tuple<T...>&& take() && {
453 if (_u.st >= state::exception_min) {
454 // Move ex out so future::~future() knows we've handled it
455 std::rethrow_exception(std::move(*this).get_exception());
457 _u.st = state::result_unavailable;
458 return std::move(this->uninitialized_get());
460 std::tuple<T...>&& get() && {
462 if (_u.st >= state::exception_min) {
463 // Move ex out so future::~future() knows we've handled it
464 std::rethrow_exception(std::move(*this).get_exception());
466 return std::move(this->uninitialized_get());
468 const std::tuple<T...>& get() const& {
470 if (_u.st >= state::exception_min) {
471 std::rethrow_exception(_u.ex);
473 return this->uninitialized_get();
475 using get0_return_type = typename internal::get0_return_type<T...>::type;
476 static get0_return_type get0(std::tuple<T...>&& x) {
477 return internal::get0_return_type<T...>::get0(std::move(x));
481 static_assert(sizeof(future_state<>) <= 8, "future_state<> is too large");
482 static_assert(sizeof(future_state<long>) <= 16, "future_state<long> is too large");
484 template <typename... T>
485 class continuation_base : public task {
487 future_state<T...> _state;
488 using future_type = future<T...>;
489 using promise_type = promise<T...>;
491 continuation_base() = default;
492 explicit continuation_base(future_state<T...>&& state) : _state(std::move(state)) {}
493 void set_state(future_state<T...>&& state) {
494 _state = std::move(state);
496 friend class internal::promise_base_with_type<T...>;
497 friend class promise<T...>;
498 friend class future<T...>;
501 template <typename Func, typename... T>
502 struct continuation final : continuation_base<T...> {
503 continuation(Func&& func, future_state<T...>&& state) : continuation_base<T...>(std::move(state)), _func(std::move(func)) {}
504 continuation(Func&& func) : _func(std::move(func)) {}
505 virtual void run_and_dispose() noexcept override {
506 _func(std::move(this->_state));
514 template <typename... T>
515 future<T...> make_exception_future(future_state_base&& state) noexcept;
517 template <typename... T, typename U>
518 void set_callback(future<T...>& fut, U* callback) noexcept;
524 enum class urgent { no, yes };
525 future_base* _future = nullptr;
527 // This points to the future_state that is currently being
528 // used. See comment above the future_state struct definition for
530 future_state_base* _state;
532 task* _task = nullptr;
534 promise_base(const promise_base&) = delete;
535 promise_base(future_state_base* state) noexcept : _state(state) {}
536 promise_base(future_base* future, future_state_base* state) noexcept;
537 promise_base(promise_base&& x) noexcept;
539 // We never need to destruct this polymorphicly, so we can make it
540 // protected instead of virtual
541 ~promise_base() noexcept;
543 void operator=(const promise_base&) = delete;
544 promise_base& operator=(promise_base&& x) = delete;
546 template<urgent Urgent>
547 void make_ready() noexcept;
550 void set_exception_impl(T&& val) noexcept {
552 _state->set_exception(std::move(val));
553 make_ready<urgent::no>();
555 // We get here if promise::get_future is called and the
556 // returned future is destroyed without creating a
558 // In older versions of seastar we would store a local
559 // copy of ex and warn in the promise destructor.
560 // Since there isn't any way for the user to clear
561 // the exception, we issue the warning from here.
562 report_failed_future(val);
566 void set_exception(future_state_base&& state) noexcept {
567 set_exception_impl(std::move(state));
570 void set_exception(std::exception_ptr&& ex) noexcept {
571 set_exception_impl(std::move(ex));
574 void set_exception(const std::exception_ptr& ex) noexcept {
575 set_exception(std::exception_ptr(ex));
578 template<typename Exception>
579 std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
580 set_exception(make_exception_ptr(std::forward<Exception>(e)));
583 friend class future_base;
584 template <typename... U> friend class seastar::future;
587 /// \brief A promise with type but no local data.
589 /// This is a promise without any local data. We use this for when the
590 /// future is created first, so we know the promise always has an
591 /// external place to point to. We cannot just use promise_base
592 /// because we need to know the type that is being stored.
593 template <typename... T>
594 class promise_base_with_type : protected internal::promise_base {
596 future_state<T...>* get_state() {
597 return static_cast<future_state<T...>*>(_state);
599 static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
601 promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
602 promise_base_with_type(future<T...>* future) noexcept : promise_base(future, &future->_state) { }
603 promise_base_with_type(promise_base_with_type&& x) noexcept : promise_base(std::move(x)) { }
604 promise_base_with_type(const promise_base_with_type&) = delete;
605 promise_base_with_type& operator=(promise_base_with_type&& x) noexcept {
606 this->~promise_base_with_type();
607 new (this) promise_base_with_type(std::move(x));
610 void operator=(const promise_base_with_type&) = delete;
612 void set_urgent_state(future_state<T...>&& state) noexcept {
614 *get_state() = std::move(state);
615 make_ready<urgent::yes>();
619 template <typename... A>
620 void set_value(A&&... a) {
621 if (auto *s = get_state()) {
622 s->set(std::forward<A>(a)...);
623 make_ready<urgent::no>();
627 #if SEASTAR_COROUTINES_TS
628 void set_coroutine(future_state<T...>& state, task& coroutine) noexcept {
634 template <typename Func>
635 void schedule(Func&& func) noexcept {
636 auto tws = new continuation<Func, T...>(std::move(func));
637 _state = &tws->_state;
640 void schedule(continuation_base<T...>* callback) noexcept {
641 _state = &callback->_state;
645 template <typename... U>
646 friend class seastar::future;
648 friend struct seastar::future_state<T...>;
653 /// \brief promise - allows a future value to be made available at a later time.
655 /// \tparam T A list of types to be carried as the result of the associated future.
656 /// A list with two or more types is deprecated; use
657 /// \c promise<std::tuple<T...>> instead.
658 template <typename... T>
659 class promise : private internal::promise_base_with_type<T...> {
660 future_state<T...> _local_state;
663 /// \brief Constructs an empty \c promise.
665 /// Creates promise with no associated future yet (see get_future()).
666 promise() noexcept : internal::promise_base_with_type<T...>(&_local_state) {}
668 /// \brief Moves a \c promise object.
669 promise(promise&& x) noexcept;
670 promise(const promise&) = delete;
671 promise& operator=(promise&& x) noexcept {
673 new (this) promise(std::move(x));
676 void operator=(const promise&) = delete;
678 /// \brief Gets the promise's associated future.
680 /// The future and promise will be remember each other, even if either or
681 /// both are moved. When \c set_value() or \c set_exception() are called
682 /// on the promise, the future will be become ready, and if a continuation
683 /// was attached to the future, it will run.
684 future<T...> get_future() noexcept;
686 /// \brief Sets the promises value
688 /// Forwards the arguments and makes them available to the associated
689 /// future. May be called either before or after \c get_future().
691 /// The arguments can have either the types the promise is
692 /// templated with, or a corresponding std::tuple. That is, given
693 /// a promise<int, double>, both calls are valid:
695 /// pr.set_value(42, 43.0);
696 /// pr.set_value(std::tuple<int, double>(42, 43.0))
697 template <typename... A>
698 void set_value(A&&... a) {
699 internal::promise_base_with_type<T...>::set_value(std::forward<A>(a)...);
702 /// \brief Marks the promise as failed
704 /// Forwards the exception argument to the future and makes it
705 /// available. May be called either before or after \c get_future().
706 void set_exception(std::exception_ptr&& ex) noexcept {
707 internal::promise_base::set_exception(std::move(ex));
710 void set_exception(const std::exception_ptr& ex) noexcept {
711 internal::promise_base::set_exception(ex);
714 /// \brief Marks the promise as failed
716 /// Forwards the exception argument to the future and makes it
717 /// available. May be called either before or after \c get_future().
718 template<typename Exception>
719 std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
720 internal::promise_base::set_exception(std::forward<Exception>(e));
723 using internal::promise_base_with_type<T...>::set_urgent_state;
725 template <typename... U>
729 /// \brief Specialization of \c promise<void>
731 /// This is an alias for \c promise<>, for generic programming purposes.
732 /// For example, You may have a \c promise<T> where \c T can legally be
735 class promise<void> : public promise<> {};
739 /// \addtogroup future-util
743 /// \brief Check whether a type is a future
745 /// This is a type trait evaluating to \c true if the given type is a
748 template <typename... T> struct is_future : std::false_type {};
751 /// \addtogroup future-util
752 template <typename... T> struct is_future<future<T...>> : std::true_type {};
757 /// \brief Converts a type to a future type, if it isn't already.
759 /// \return Result in member type 'type'.
760 template <typename T>
763 template <typename T>
765 /// If \c T is a future, \c T; otherwise \c future<T>
766 using type = future<T>;
767 /// The promise type associated with \c type.
768 using promise_type = promise<T>;
769 /// The value tuple type associated with \c type
770 using value_type = std::tuple<T>;
772 /// Apply a function to an argument list (expressed as a tuple)
773 /// and return the result, as a future (if it wasn't already).
774 template<typename Func, typename... FuncArgs>
775 static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
777 /// Apply a function to an argument list
778 /// and return the result, as a future (if it wasn't already).
779 template<typename Func, typename... FuncArgs>
780 static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
782 /// Convert a value or a future to a future
783 static inline type convert(T&& value) { return make_ready_future<T>(std::move(value)); }
784 static inline type convert(type&& value) { return std::move(value); }
786 /// Convert the tuple representation into a future
787 static type from_tuple(value_type&& value);
788 /// Convert the tuple representation into a future
789 static type from_tuple(const value_type& value);
791 /// Makes an exceptional future of type \ref type.
792 template <typename Arg>
793 static type make_exception_future(Arg&& arg);
798 struct futurize<void> {
799 using type = future<>;
800 using promise_type = promise<>;
801 using value_type = std::tuple<>;
803 template<typename Func, typename... FuncArgs>
804 static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
806 template<typename Func, typename... FuncArgs>
807 static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
809 static inline type from_tuple(value_type&& value);
810 static inline type from_tuple(const value_type& value);
812 template <typename Arg>
813 static type make_exception_future(Arg&& arg);
816 template <typename... Args>
817 struct futurize<future<Args...>> {
818 using type = future<Args...>;
819 using promise_type = promise<Args...>;
820 using value_type = std::tuple<Args...>;
822 template<typename Func, typename... FuncArgs>
823 static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
825 template<typename Func, typename... FuncArgs>
826 static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
828 static inline type from_tuple(value_type&& value);
829 static inline type from_tuple(const value_type& value);
831 static inline type convert(Args&&... values) { return make_ready_future<Args...>(std::move(values)...); }
832 static inline type convert(type&& value) { return std::move(value); }
834 template <typename Arg>
835 static type make_exception_future(Arg&& arg);
839 // Converts a type to a future type, if it isn't already.
840 template <typename T>
841 using futurize_t = typename futurize<T>::type;
847 template <typename T>
848 concept bool Future = is_future<T>::value;
850 template <typename Func, typename... T>
851 concept bool CanApply = requires (Func f, T... args) {
852 f(std::forward<T>(args)...);
855 template <typename Func, typename Return, typename... T>
856 concept bool ApplyReturns = requires (Func f, T... args) {
857 { f(std::forward<T>(args)...) } -> Return;
860 template <typename Func, typename... T>
861 concept bool ApplyReturnsAnyFuture = requires (Func f, T... args) {
862 requires is_future<decltype(f(std::forward<T>(args)...))>::value;
867 /// \addtogroup future-module
872 promise_base* _promise;
873 future_base() noexcept : _promise(nullptr) {}
874 future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
875 _promise->_future = this;
876 _promise->_state = state;
879 future_base(future_base&& x, future_state_base* state) noexcept : _promise(x._promise) {
880 if (auto* p = _promise) {
886 ~future_base() noexcept {
892 promise_base* detach_promise() noexcept {
893 _promise->_state = nullptr;
894 _promise->_future = nullptr;
895 return std::exchange(_promise, nullptr);
898 friend class promise_base;
901 template <bool IsVariadic>
902 struct warn_variadic_future {
903 // Non-varidic case, do nothing
904 void check_deprecation() {}
908 // Note: placing the deprecated attribute on the class specialization has no effect.
910 struct warn_variadic_future<true> {
911 // Variadic case, has deprecation attribute
912 [[deprecated("Variadic future<> with more than one template parmeter is deprecated, replace with future<std::tuple<...>>")]]
913 void check_deprecation() {}
918 /// \brief A representation of a possibly not-yet-computed value.
920 /// A \c future represents a value that has not yet been computed
921 /// (an asynchronous computation). It can be in one of several
923 /// - unavailable: the computation has not been completed yet
924 /// - value: the computation has been completed successfully and a
925 /// value is available.
926 /// - failed: the computation completed with an exception.
928 /// methods in \c future allow querying the state and, most importantly,
929 /// scheduling a \c continuation to be executed when the future becomes
930 /// available. Only one such continuation may be scheduled.
932 /// A \ref future should not be discarded before it is waited upon and
933 /// its result is extracted. Discarding a \ref future means that the
934 /// computed value becomes inaccessible, but more importantly, any
935 /// exceptions raised from the computation will disappear unchecked as
936 /// well. Another very important consequence is potentially unbounded
937 /// resource consumption due to the launcher of the deserted
938 /// continuation not being able track the amount of in-progress
939 /// continuations, nor their individual resource consumption.
940 /// To prevent accidental discarding of futures, \ref future is
941 /// declared `[[nodiscard]]` if the compiler supports it. Also, when a
942 /// discarded \ref future resolves with an error a warning is logged
944 /// That said there can be legitimate cases where a \ref future is
945 /// discarded. The most prominent example is launching a new
946 /// [fiber](\ref fiber-module), or in other words, moving a continuation
947 /// chain to the background (off the current [fiber](\ref fiber-module)).
948 /// Even if a \ref future is discarded purposefully, it is still strongly
949 /// advisable to wait on it indirectly (via a \ref gate or
950 /// \ref semaphore), control their concurrency, their resource consumption
951 /// and handle any errors raised from them.
953 /// \tparam T A list of types to be carried as the result of the future,
954 /// similar to \c std::tuple<T...>. An empty list (\c future<>)
955 /// means that there is no result, and an available future only
956 /// contains a success/failure indication (and in the case of a
957 /// failure, an exception).
958 /// A list with two or more types is deprecated; use
959 /// \c future<std::tuple<T...>> instead.
960 template <typename... T>
961 class SEASTAR_NODISCARD future : private internal::future_base, internal::warn_variadic_future<(sizeof...(T) > 1)> {
962 future_state<T...> _state;
963 static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
965 // This constructor creates a future that is not ready but has no
966 // associated promise yet. The use case is to have a less flexible
967 // but more efficient future/promise pair where we know that
968 // promise::set_value cannot possibly be called without a matching
969 // future and so that promise doesn't need to store a
971 future(future_for_get_promise_marker m) { }
973 future(promise<T...>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
974 template <typename... A>
975 future(ready_future_marker m, A&&... a) : _state(m, std::forward<A>(a)...) { }
976 future(exception_future_marker m, std::exception_ptr&& ex) noexcept : _state(m, std::move(ex)) { }
977 future(exception_future_marker m, future_state_base&& state) noexcept : _state(m, std::move(state)) { }
978 [[gnu::always_inline]]
979 explicit future(future_state<T...>&& state) noexcept
980 : _state(std::move(state)) {
981 this->check_deprecation();
983 internal::promise_base_with_type<T...> get_promise() noexcept {
985 return internal::promise_base_with_type<T...>(this);
987 internal::promise_base_with_type<T...>* detach_promise() {
988 return static_cast<internal::promise_base_with_type<T...>*>(future_base::detach_promise());
990 template <typename Func>
991 void schedule(Func&& func) noexcept {
992 if (_state.available() || !_promise) {
993 if (__builtin_expect(!_state.available() && !_promise, false)) {
994 _state.set_to_broken_promise();
996 ::seastar::schedule(new continuation<Func, T...>(std::move(func), std::move(_state)));
999 detach_promise()->schedule(std::move(func));
1000 _state._u.st = future_state_base::state::invalid;
1004 [[gnu::always_inline]]
1005 future_state<T...>&& get_available_state_ref() noexcept {
1009 return std::move(_state);
1013 future<T...> rethrow_with_nested() {
1015 return internal::current_exception_as_future<T...>();
1018 // Encapsulate the current exception into the
1019 // std::nested_exception because the current libstdc++
1020 // implementation has a bug requiring the value of a
1021 // std::throw_with_nested() parameter to be of a polymorphic
1024 std::nested_exception f_ex;
1028 std::throw_with_nested(f_ex);
1030 __builtin_unreachable();
1034 template<typename... U>
1035 friend class shared_future;
1037 /// \brief The data type carried by the future.
1038 using value_type = std::tuple<T...>;
1039 /// \brief The data type carried by the future.
1040 using promise_type = promise<T...>;
1041 /// \brief Moves the future into a new object.
1042 [[gnu::always_inline]]
1043 future(future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1044 future(const future&) = delete;
1045 future& operator=(future&& x) noexcept {
1047 new (this) future(std::move(x));
1050 void operator=(const future&) = delete;
1051 /// \brief gets the value returned by the computation
1053 /// Requires that the future be available. If the value
1054 /// was computed successfully, it is returned (as an
1055 /// \c std::tuple). Otherwise, an exception is thrown.
1057 /// If get() is called in a \ref seastar::thread context,
1058 /// then it need not be available; instead, the thread will
1059 /// be paused until the future becomes available.
1060 [[gnu::always_inline]]
1061 std::tuple<T...>&& get() {
1062 if (!_state.available()) {
1065 return get_available_state_ref().take();
1068 [[gnu::always_inline]]
1069 std::exception_ptr get_exception() {
1070 return get_available_state_ref().get_exception();
1073 /// Gets the value returned by the computation.
1075 /// Similar to \ref get(), but instead of returning a
1076 /// tuple, returns the first value of the tuple. This is
1077 /// useful for the common case of a \c future<T> with exactly
1078 /// one type parameter.
1080 /// Equivalent to: \c std::get<0>(f.get()).
1081 typename future_state<T...>::get0_return_type get0() {
1082 return future_state<T...>::get0(get());
1085 /// Wait for the future to be available (in a seastar::thread)
1087 /// When called from a seastar::thread, this function blocks the
1088 /// thread until the future is availble. Other threads and
1089 /// continuations continue to execute; only the thread is blocked.
1090 void wait() noexcept {
1091 if (!_state.available()) {
1096 class thread_wake_task final : public continuation_base<T...> {
1097 thread_context* _thread;
1098 future* _waiting_for;
1100 thread_wake_task(thread_context* thread, future* waiting_for)
1101 : _thread(thread), _waiting_for(waiting_for) {
1103 virtual void run_and_dispose() noexcept override {
1104 _waiting_for->_state = std::move(this->_state);
1105 thread_impl::switch_in(_thread);
1106 // no need to delete, since this is always allocated on
1110 void do_wait() noexcept {
1111 if (__builtin_expect(!_promise, false)) {
1112 _state.set_to_broken_promise();
1115 auto thread = thread_impl::get();
1117 thread_wake_task wake_task{thread, this};
1118 detach_promise()->schedule(static_cast<continuation_base<T...>*>(&wake_task));
1119 thread_impl::switch_out(thread);
1123 /// \brief Checks whether the future is available.
1125 /// \return \c true if the future has a value, or has failed.
1126 [[gnu::always_inline]]
1127 bool available() const noexcept {
1128 return _state.available();
1131 /// \brief Checks whether the future has failed.
1133 /// \return \c true if the future is availble and has failed.
1134 [[gnu::always_inline]]
1135 bool failed() const noexcept {
1136 return _state.failed();
1139 /// \brief Schedule a block of code to run when the future is ready.
1141 /// Schedules a function (often a lambda) to run when the future becomes
1142 /// available. The function is called with the result of this future's
1143 /// computation as parameters. The return value of the function becomes
1144 /// the return value of then(), itself as a future; this allows then()
1145 /// calls to be chained.
1147 /// If the future failed, the function is not called, and the exception
1148 /// is propagated into the return value of then().
1150 /// \param func - function to be called when the future becomes available,
1151 /// unless it has failed.
1152 /// \return a \c future representing the return value of \c func, applied
1153 /// to the eventual value of this future.
1154 template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1155 GCC6_CONCEPT( requires ::seastar::CanApply<Func, T...> )
1157 then(Func&& func) noexcept {
1158 #ifndef SEASTAR_TYPE_ERASE_MORE
1159 return then_impl(std::move(func));
1161 using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1162 return then_impl(noncopyable_function<Result (T&&...)>([func = std::forward<Func>(func)] (T&&... args) mutable {
1163 return futurator::apply(func, std::forward_as_tuple(std::move(args)...));
1170 template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1172 then_impl(Func&& func) noexcept {
1173 using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1174 if (available() && !need_preempt()) {
1176 return futurator::make_exception_future(static_cast<future_state_base&&>(get_available_state_ref()));
1178 return futurator::apply(std::forward<Func>(func), get_available_state_ref().take_value());
1181 typename futurator::type fut(future_for_get_promise_marker{});
1182 // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1183 // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1186 memory::disable_failure_guard dfg;
1187 schedule([pr = fut.get_promise(), func = std::forward<Func>(func)] (future_state<T...>&& state) mutable {
1188 if (state.failed()) {
1189 pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1191 futurator::apply(std::forward<Func>(func), std::move(state).get_value()).forward_to(std::move(pr));
1199 /// \brief Schedule a block of code to run when the future is ready, allowing
1200 /// for exception handling.
1202 /// Schedules a function (often a lambda) to run when the future becomes
1203 /// available. The function is called with the this future as a parameter;
1204 /// it will be in an available state. The return value of the function becomes
1205 /// the return value of then_wrapped(), itself as a future; this allows
1206 /// then_wrapped() calls to be chained.
1208 /// Unlike then(), the function will be called for both value and exceptional
1211 /// \param func - function to be called when the future becomes available,
1212 /// \return a \c future representing the return value of \c func, applied
1213 /// to the eventual value of this future.
1214 template <typename Func, typename FuncResult = std::result_of_t<Func(future)>>
1215 GCC6_CONCEPT( requires ::seastar::CanApply<Func, future> )
1216 futurize_t<FuncResult>
1217 then_wrapped(Func&& func) & noexcept {
1218 return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1221 template <typename Func, typename FuncResult = std::result_of_t<Func(future&&)>>
1222 GCC6_CONCEPT( requires ::seastar::CanApply<Func, future&&> )
1223 futurize_t<FuncResult>
1224 then_wrapped(Func&& func) && noexcept {
1225 return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1230 template <bool AsSelf, typename FuncResult, typename Func>
1231 futurize_t<FuncResult>
1232 then_wrapped_maybe_erase(Func&& func) noexcept {
1233 #ifndef SEASTAR_TYPE_ERASE_MORE
1234 return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1236 using futurator = futurize<FuncResult>;
1237 return then_wrapped_common<AsSelf, FuncResult>(noncopyable_function<typename futurator::type (future&&)>([func = std::forward<Func>(func)] (future&& f) mutable {
1238 return futurator::apply(std::forward<Func>(func), std::move(f));
1243 template <bool AsSelf, typename FuncResult, typename Func>
1244 futurize_t<FuncResult>
1245 then_wrapped_common(Func&& func) noexcept {
1246 using futurator = futurize<FuncResult>;
1247 if (available() && !need_preempt()) {
1248 // TODO: after dropping C++14 support use `if constexpr ()` instead.
1253 return futurator::apply(std::forward<Func>(func), std::move(*this));
1255 return futurator::apply(std::forward<Func>(func), future(get_available_state_ref()));
1258 typename futurator::type fut(future_for_get_promise_marker{});
1259 // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1260 // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1263 memory::disable_failure_guard dfg;
1264 schedule([pr = fut.get_promise(), func = std::forward<Func>(func)] (future_state<T...>&& state) mutable {
1265 futurator::apply(std::forward<Func>(func), future(std::move(state))).forward_to(std::move(pr));
1271 void forward_to(internal::promise_base_with_type<T...>&& pr) noexcept {
1272 if (_state.available()) {
1273 pr.set_urgent_state(std::move(_state));
1275 *detach_promise() = std::move(pr);
1280 /// \brief Satisfy some \ref promise object with this future as a result.
1282 /// Arranges so that when this future is resolve, it will be used to
1283 /// satisfy an unrelated promise. This is similar to scheduling a
1284 /// continuation that moves the result of this future into the promise
1285 /// (using promise::set_value() or promise::set_exception(), except
1286 /// that it is more efficient.
1288 /// \param pr a promise that will be fulfilled with the results of this
1290 void forward_to(promise<T...>&& pr) noexcept {
1291 if (_state.available()) {
1292 pr.set_urgent_state(std::move(_state));
1293 } else if (&pr._local_state != pr._state) {
1294 // The only case when _state points to _local_state is
1295 // when get_future was never called. Given that pr will
1296 // soon be destroyed, we know get_future will never be
1297 // called and we can just ignore this request.
1298 *detach_promise() = std::move(pr);
1305 * Finally continuation for statements that require waiting for the result.
1306 * I.e. you need to "finally" call a function that returns a possibly
1307 * unavailable future. The returned future will be "waited for", any
1308 * exception generated will be propagated, but the return value is ignored.
1309 * I.e. the original return value (the future upon which you are making this
1310 * call) will be preserved.
1312 * If the original return value or the callback return value is an
1313 * exceptional future it will be propagated.
1315 * If both of them are exceptional - the std::nested_exception exception
1316 * with the callback exception on top and the original future exception
1317 * nested will be propagated.
1319 template <typename Func>
1320 GCC6_CONCEPT( requires ::seastar::CanApply<Func> )
1321 future<T...> finally(Func&& func) noexcept {
1322 return then_wrapped(finally_body<Func, is_future<std::result_of_t<Func()>>::value>(std::forward<Func>(func)));
1326 template <typename Func, bool FuncReturnsFuture>
1327 struct finally_body;
1329 template <typename Func>
1330 struct finally_body<Func, true> {
1333 finally_body(Func&& func) : _func(std::forward<Func>(func))
1336 future<T...> operator()(future<T...>&& result) {
1337 using futurator = futurize<std::result_of_t<Func()>>;
1338 return futurator::apply(_func).then_wrapped([result = std::move(result)](auto f_res) mutable {
1339 if (!f_res.failed()) {
1340 return std::move(result);
1345 return result.rethrow_with_nested();
1347 __builtin_unreachable();
1353 template <typename Func>
1354 struct finally_body<Func, false> {
1357 finally_body(Func&& func) : _func(std::forward<Func>(func))
1360 future<T...> operator()(future<T...>&& result) {
1363 return std::move(result);
1365 return result.rethrow_with_nested();
1370 /// \brief Terminate the program if this future fails.
1372 /// Terminates the entire program is this future resolves
1373 /// to an exception. Use with caution.
1374 future<> or_terminate() noexcept {
1375 return then_wrapped([] (auto&& f) {
1379 engine_exit(std::current_exception());
1384 /// \brief Discards the value carried by this future.
1386 /// Converts the future into a no-value \c future<>, by
1387 /// ignoring any result. Exceptions are propagated unchanged.
1388 future<> discard_result() noexcept {
1389 return then([] (T&&...) {});
1392 /// \brief Handle the exception carried by this future.
1394 /// When the future resolves, if it resolves with an exception,
1395 /// handle_exception(func) replaces the exception with the value
1396 /// returned by func. The exception is passed (as a std::exception_ptr)
1397 /// as a parameter to func; func may return the replacement value
1398 /// immediately (T or std::tuple<T...>) or in the future (future<T...>)
1399 /// and is even allowed to return (or throw) its own exception.
1401 /// The idiom fut.discard_result().handle_exception(...) can be used
1402 /// to handle an exception (if there is one) without caring about the
1403 /// successful value; Because handle_exception() is used here on a
1404 /// future<>, the handler function does not need to return anything.
1405 template <typename Func>
1407 GCC6_CONCEPT( requires ::seastar::ApplyReturns<Func, future<T...>, std::exception_ptr>
1408 || (sizeof...(T) == 0 && ::seastar::ApplyReturns<Func, void, std::exception_ptr>)
1409 || (sizeof...(T) == 1 && ::seastar::ApplyReturns<Func, T..., std::exception_ptr>)
1411 future<T...> handle_exception(Func&& func) noexcept {
1412 using func_ret = std::result_of_t<Func(std::exception_ptr)>;
1413 return then_wrapped([func = std::forward<Func>(func)]
1414 (auto&& fut) mutable -> future<T...> {
1415 if (!fut.failed()) {
1416 return make_ready_future<T...>(fut.get());
1418 return futurize<func_ret>::apply(func, fut.get_exception());
1423 /// \brief Handle the exception of a certain type carried by this future.
1425 /// When the future resolves, if it resolves with an exception of a type that
1426 /// provided callback receives as a parameter, handle_exception(func) replaces
1427 /// the exception with the value returned by func. The exception is passed (by
1428 /// reference) as a parameter to func; func may return the replacement value
1429 /// immediately (T or std::tuple<T...>) or in the future (future<T...>)
1430 /// and is even allowed to return (or throw) its own exception.
1431 /// If exception, that future holds, does not match func parameter type
1432 /// it is propagated as is.
1433 template <typename Func>
1434 future<T...> handle_exception_type(Func&& func) noexcept {
1435 using trait = function_traits<Func>;
1436 static_assert(trait::arity == 1, "func can take only one parameter");
1437 using ex_type = typename trait::template arg<0>::type;
1438 using func_ret = typename trait::return_type;
1439 return then_wrapped([func = std::forward<Func>(func)]
1440 (auto&& fut) mutable -> future<T...> {
1442 return make_ready_future<T...>(fut.get());
1443 } catch(ex_type& ex) {
1444 return futurize<func_ret>::apply(func, ex);
1449 /// \brief Ignore any result hold by this future
1451 /// Ignore any result (value or exception) hold by this future.
1452 /// Use with caution since usually ignoring exception is not what
1454 void ignore_ready_future() noexcept {
1458 #if SEASTAR_COROUTINES_TS
1459 void set_coroutine(task& coroutine) noexcept {
1460 assert(!_state.available());
1462 detach_promise()->set_coroutine(_state, coroutine);
1466 void set_callback(continuation_base<T...>* callback) noexcept {
1467 if (_state.available()) {
1468 callback->set_state(get_available_state_ref());
1469 ::seastar::schedule(callback);
1472 detach_promise()->schedule(callback);
1478 template <typename... U>
1479 friend class future;
1480 template <typename... U>
1481 friend class promise;
1482 template <typename... U>
1483 friend class internal::promise_base_with_type;
1484 template <typename... U, typename... A>
1485 friend future<U...> make_ready_future(A&&... value);
1486 template <typename... U>
1487 friend future<U...> make_exception_future(std::exception_ptr&& ex) noexcept;
1488 template <typename... U, typename Exception>
1489 friend future<U...> make_exception_future(Exception&& ex) noexcept;
1490 template <typename... U>
1491 friend future<U...> internal::make_exception_future(future_state_base&& state) noexcept;
1492 template <typename... U, typename V>
1493 friend void internal::set_callback(future<U...>&, V*) noexcept;
1497 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1498 : _future(future), _state(state) {
1499 _future->_promise = this;
1502 template <typename... T>
1505 promise<T...>::get_future() noexcept {
1506 assert(!this->_future && this->_state && !this->_task);
1507 return future<T...>(this);
1510 template <typename... T>
1512 promise<T...>::promise(promise&& x) noexcept : internal::promise_base_with_type<T...>(std::move(x)) {
1513 if (this->_state == &x._local_state) {
1514 this->_state = &_local_state;
1515 _local_state = std::move(x._local_state);
1519 template <typename... T, typename... A>
1521 future<T...> make_ready_future(A&&... value) {
1522 return future<T...>(ready_future_marker(), std::forward<A>(value)...);
1525 template <typename... T>
1527 future<T...> make_exception_future(std::exception_ptr&& ex) noexcept {
1528 return future<T...>(exception_future_marker(), std::move(ex));
1531 template <typename... T>
1533 future<T...> internal::make_exception_future(future_state_base&& state) noexcept {
1534 return future<T...>(exception_future_marker(), std::move(state));
1537 template <typename... T>
1538 future<T...> internal::current_exception_as_future() noexcept {
1539 return internal::make_exception_future<T...>(future_state_base::current_exception());
1542 void log_exception_trace() noexcept;
1544 /// \brief Creates a \ref future in an available, failed state.
1546 /// Creates a \ref future object that is already resolved in a failed
1547 /// state. This no I/O needs to be performed to perform a computation
1548 /// (for example, because the connection is closed and we cannot read
1550 template <typename... T, typename Exception>
1552 future<T...> make_exception_future(Exception&& ex) noexcept {
1553 log_exception_trace();
1554 return make_exception_future<T...>(std::make_exception_ptr(std::forward<Exception>(ex)));
1561 template<typename T>
1562 template<typename Func, typename... FuncArgs>
1563 typename futurize<T>::type futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1565 return convert(::seastar::apply(std::forward<Func>(func), std::move(args)));
1567 return internal::current_exception_as_future<T>();
1571 template<typename T>
1572 template<typename Func, typename... FuncArgs>
1573 typename futurize<T>::type futurize<T>::apply(Func&& func, FuncArgs&&... args) noexcept {
1575 return convert(func(std::forward<FuncArgs>(args)...));
1577 return internal::current_exception_as_future<T>();
1581 template <typename Ret> // Ret = void | future<>
1582 struct do_void_futurize_helper;
1585 struct do_void_futurize_helper<void> {
1586 template <typename Func, typename... FuncArgs>
1587 static future<> apply(Func&& func, FuncArgs&&... args) noexcept {
1589 func(std::forward<FuncArgs>(args)...);
1590 return make_ready_future<>();
1592 return internal::current_exception_as_future<>();
1596 template<typename Func, typename... FuncArgs>
1597 static future<> apply_tuple(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1599 ::seastar::apply(std::forward<Func>(func), std::move(args));
1600 return make_ready_future<>();
1602 return internal::current_exception_as_future<>();
1608 struct do_void_futurize_helper<future<>> {
1609 template <typename Func, typename... FuncArgs>
1610 static future<> apply(Func&& func, FuncArgs&&... args) noexcept {
1612 return func(std::forward<FuncArgs>(args)...);
1614 return internal::current_exception_as_future<>();
1618 template<typename Func, typename... FuncArgs>
1619 static future<> apply_tuple(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1621 return ::seastar::apply(std::forward<Func>(func), std::move(args));
1623 return internal::current_exception_as_future<>();
1628 template <typename Func, typename... FuncArgs>
1629 using void_futurize_helper = do_void_futurize_helper<std::result_of_t<Func(FuncArgs&&...)>>;
1631 template<typename Func, typename... FuncArgs>
1632 typename futurize<void>::type futurize<void>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1633 return void_futurize_helper<Func, FuncArgs...>::apply_tuple(std::forward<Func>(func), std::move(args));
1636 template<typename Func, typename... FuncArgs>
1637 typename futurize<void>::type futurize<void>::apply(Func&& func, FuncArgs&&... args) noexcept {
1638 return void_futurize_helper<Func, FuncArgs...>::apply(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1641 template<typename... Args>
1642 template<typename Func, typename... FuncArgs>
1643 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1645 return ::seastar::apply(std::forward<Func>(func), std::move(args));
1647 return internal::current_exception_as_future<Args...>();
1651 template<typename... Args>
1652 template<typename Func, typename... FuncArgs>
1653 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, FuncArgs&&... args) noexcept {
1655 return func(std::forward<FuncArgs>(args)...);
1657 return internal::current_exception_as_future<Args...>();
1661 template <typename T>
1662 template <typename Arg>
1665 futurize<T>::make_exception_future(Arg&& arg) {
1666 using ::seastar::make_exception_future;
1667 using ::seastar::internal::make_exception_future;
1668 return make_exception_future<T>(std::forward<Arg>(arg));
1671 template <typename... T>
1672 template <typename Arg>
1675 futurize<future<T...>>::make_exception_future(Arg&& arg) {
1676 using ::seastar::make_exception_future;
1677 using ::seastar::internal::make_exception_future;
1678 return make_exception_future<T...>(std::forward<Arg>(arg));
1681 template <typename Arg>
1684 futurize<void>::make_exception_future(Arg&& arg) {
1685 using ::seastar::make_exception_future;
1686 using ::seastar::internal::make_exception_future;
1687 return make_exception_future<>(std::forward<Arg>(arg));
1690 template <typename T>
1693 futurize<T>::from_tuple(std::tuple<T>&& value) {
1694 return make_ready_future<T>(std::move(value));
1697 template <typename T>
1700 futurize<T>::from_tuple(const std::tuple<T>& value) {
1701 return make_ready_future<T>(value);
1706 futurize<void>::from_tuple(std::tuple<>&& value) {
1707 return make_ready_future<>();
1712 futurize<void>::from_tuple(const std::tuple<>& value) {
1713 return make_ready_future<>();
1716 template <typename... Args>
1719 futurize<future<Args...>>::from_tuple(std::tuple<Args...>&& value) {
1720 return make_ready_future<Args...>(std::move(value));
1723 template <typename... Args>
1726 futurize<future<Args...>>::from_tuple(const std::tuple<Args...>& value) {
1727 return make_ready_future<Args...>(value);
1730 template<typename Func, typename... Args>
1731 auto futurize_apply(Func&& func, Args&&... args) {
1732 using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
1733 return futurator::apply(std::forward<Func>(func), std::forward<Args>(args)...);
1736 namespace internal {
1738 template <typename... T, typename U>
1740 void set_callback(future<T...>& fut, U* callback) noexcept {
1741 // It would be better to use continuation_base<T...> for U, but
1742 // then a derived class of continuation_base<T...> won't be matched
1743 return fut.set_callback(callback);