Seastar
High performance C++ framework for concurrent servers
future.hh
1 /*
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.
6  *
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
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
16  * under the License.
17  */
18 /*
19  * Copyright (C) 2015 Cloudius Systems, Ltd.
20  */
21 
22 #pragma once
23 
24 #include <cassert>
25 #include <atomic>
26 #include <cstdlib>
27 #include <cstring>
28 #include <functional>
29 #include <memory>
30 #include <stdexcept>
31 #include <type_traits>
32 #include <utility>
33 #include <seastar/core/task.hh>
34 #include <seastar/core/thread_impl.hh>
35 #include <seastar/core/function_traits.hh>
36 #include <seastar/util/critical_alloc_section.hh>
37 #include <seastar/util/concepts.hh>
38 #include <seastar/util/noncopyable_function.hh>
39 #include <seastar/util/backtrace.hh>
40 #include <seastar/util/std-compat.hh>
41 
42 namespace seastar {
43 
44 struct nested_exception : public std::exception {
45  std::exception_ptr inner;
46  std::exception_ptr outer;
47  nested_exception(std::exception_ptr inner, std::exception_ptr outer) noexcept;
49  nested_exception(const nested_exception&) noexcept;
50  [[noreturn]] void rethrow_nested() const;
51  virtual const char* what() const noexcept override;
52 };
53 
77 
134 
140 
141 
144 
145 #if SEASTAR_API_LEVEL < 6
146 template <class... T>
147 #else
148 template <class T = void>
149 #endif
150 class promise;
151 
152 template <class SEASTAR_ELLIPSIS T>
153 class future;
154 
155 template <typename... T>
156 class shared_future;
157 
158 struct future_state_base;
159 
166 template <typename... T, typename... A>
167 future<T...> make_ready_future(A&&... value) noexcept;
168 
175 template <typename... T>
176 future<T...> make_exception_future(std::exception_ptr&& value) noexcept;
177 
178 template <typename... T>
179 future<T...> make_exception_future(const std::exception_ptr& ex) noexcept {
180  return make_exception_future<T...>(std::exception_ptr(ex));
181 }
182 
183 template <typename... T>
184 future<T...> make_exception_future(std::exception_ptr& ex) noexcept {
185  return make_exception_future<T...>(static_cast<const std::exception_ptr&>(ex));
186 }
187 
188 template <typename... T>
189 future<T...> make_exception_future(const std::exception_ptr&& ex) noexcept {
190  // as ex is const, we cannot move it, but can copy it.
191  return make_exception_future<T...>(std::exception_ptr(ex));
192 }
193 
195 void engine_exit(std::exception_ptr eptr = {});
196 
197 void report_failed_future(const std::exception_ptr& ex) noexcept;
198 
199 void report_failed_future(const future_state_base& state) noexcept;
200 
201 void with_allow_abandoned_failed_futures(unsigned count, noncopyable_function<void ()> func);
202 
204 
211 struct broken_promise : std::logic_error {
212  broken_promise();
213 };
214 
220 template <typename... T>
221 future<T...> current_exception_as_future() noexcept;
222 
223 extern template
225 
226 namespace internal {
227 #if SEASTAR_API_LEVEL < 6
228 template <class... T>
229 #else
230 template <class T = void>
231 #endif
232 class promise_base_with_type;
233 class promise_base;
234 
235 struct monostate {};
236 
237 template <typename... T>
238 struct future_stored_type;
239 
240 template <>
241 struct future_stored_type<> {
242 #if SEASTAR_API_LEVEL < 5
243  using type = std::tuple<>;
244 #else
245  using type = monostate;
246 #endif
247 };
248 
249 template <typename T>
250 struct future_stored_type<T> {
251 #if SEASTAR_API_LEVEL < 5
252  using type = std::tuple<T>;
253 #else
254  using type = std::conditional_t<std::is_void_v<T>, internal::monostate, T>;
255 #endif
256 };
257 
258 template <typename... T>
259 using future_stored_type_t = typename future_stored_type<T...>::type;
260 
261 template<typename T>
262 #if SEASTAR_API_LEVEL < 5
263 using future_tuple_type_t = T;
264 #else
265 using future_tuple_type_t = std::conditional_t<std::is_same_v<T, monostate>, std::tuple<>, std::tuple<T>>;
266 #endif
267 
268 // 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
269 // fails the build even if it is in the non enabled side of std::conditional.
270 template <typename T>
271 struct get0_return_type;
272 
273 template <>
274 struct get0_return_type<std::tuple<>> {
275  using type = void;
276  static type get0(std::tuple<>) { }
277 };
278 
279 template <typename T0, typename... T>
280 struct get0_return_type<std::tuple<T0, T...>> {
281  using type = T0;
282  static type get0(std::tuple<T0, T...> v) { return std::get<0>(std::move(v)); }
283 };
284 
285 template<typename T>
286 using maybe_wrap_ref = std::conditional_t<std::is_reference_v<T>, std::reference_wrapper<std::remove_reference_t<T>>, T>;
287 
295 template <typename T, bool is_trivial_class>
296 struct uninitialized_wrapper_base;
297 
298 template <typename T>
299 struct uninitialized_wrapper_base<T, false> {
300  using tuple_type = future_tuple_type_t<T>;
301  union any {
302  any() noexcept {}
303  ~any() {}
304  // T can be a reference, so wrap it.
305  maybe_wrap_ref<T> value;
306  } _v;
307 
308 public:
309  uninitialized_wrapper_base() noexcept = default;
310  template<typename... U>
311  std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>, void>
312  uninitialized_set(U&&... vs) {
313  new (&_v.value) maybe_wrap_ref<T>{T(std::forward<U>(vs)...)};
314  }
315  void uninitialized_set(tuple_type&& v) {
316  uninitialized_set(std::move(std::get<0>(v)));
317  }
318  void uninitialized_set(const tuple_type& v) {
319  uninitialized_set(std::get<0>(v));
320  }
321  maybe_wrap_ref<T>& uninitialized_get() {
322  return _v.value;
323  }
324  const maybe_wrap_ref<T>& uninitialized_get() const {
325  return _v.value;
326  }
327 };
328 
329 template <typename T> struct uninitialized_wrapper_base<T, true> : private T {
330  using tuple_type = future_tuple_type_t<T>;
331  uninitialized_wrapper_base() noexcept = default;
332  template<typename... U>
333  std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>, void>
334  uninitialized_set(U&&... vs) {
335  new (this) T(std::forward<U>(vs)...);
336  }
337  void uninitialized_set(tuple_type&& v) {
338  if constexpr (std::tuple_size_v<tuple_type> != 0) {
339  uninitialized_set(std::move(std::get<0>(v)));
340  }
341  }
342  void uninitialized_set(const tuple_type& v) {
343  if constexpr (std::tuple_size_v<tuple_type> != 0) {
344  uninitialized_set(std::get<0>(v));
345  }
346  }
347  T& uninitialized_get() {
348  return *this;
349  }
350  const T& uninitialized_get() const {
351  return *this;
352  }
353 };
354 
355 template <typename T>
356 constexpr bool can_inherit =
357 #ifdef _LIBCPP_VERSION
358 // We expect std::tuple<> to be trivially constructible and
359 // destructible. That is not the case with libc++
360 // (https://bugs.llvm.org/show_bug.cgi?id=41714). We could avoid this
361 // optimization when using libc++ and relax the asserts, but
362 // inspection suggests that std::tuple<> is trivial, it is just not
363 // marked as such.
364  std::is_same<std::tuple<>, T>::value ||
365 #endif
366  (std::is_trivially_destructible<T>::value && std::is_trivially_constructible<T>::value &&
367  std::is_class<T>::value && !std::is_final<T>::value);
368 
369 // The objective is to avoid extra space for empty types like std::tuple<>. We could use std::is_empty_v, but it is
370 // better to check that both the constructor and destructor can be skipped.
371 template <typename T>
372 struct uninitialized_wrapper
373  : public uninitialized_wrapper_base<T, can_inherit<T>> {};
374 
375 template <typename T>
376 struct is_trivially_move_constructible_and_destructible {
377  static constexpr bool value = std::is_trivially_move_constructible<T>::value && std::is_trivially_destructible<T>::value;
378 };
379 
380 template <bool... v>
381 struct all_true : std::false_type {};
382 
383 template <>
384 struct all_true<> : std::true_type {};
385 
386 template <bool... v>
387 struct all_true<true, v...> : public all_true<v...> {};
388 
389 template<typename T>
390 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper;
391 
392 template <typename... T>
393 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper<std::tuple<T...>> {
394  static constexpr bool value = all_true<is_trivially_move_constructible_and_destructible<T>::value...>::value;
395 };
396 
397 template <typename T>
398 static constexpr bool is_tuple_effectively_trivially_move_constructible_and_destructible =
399  is_tuple_effectively_trivially_move_constructible_and_destructible_helper<T>::value;
400 
401 }
402 
403 //
404 // A future/promise pair maintain one logical value (a future_state).
405 // There are up to three places that can store it, but only one is
406 // active at any time.
407 //
408 // - in the promise _local_state member variable
409 //
410 // This is necessary because a promise is created first and there
411 // would be nowhere else to put the value.
412 //
413 // - in the future _state variable
414 //
415 // This is used anytime a future exists and then has not been called
416 // yet. This guarantees a simple access to the value for any code
417 // that already has a future.
418 //
419 // - in the task associated with the .then() clause (after .then() is called,
420 // if a value was not set)
421 //
422 //
423 // The promise maintains a pointer to the state, which is modified as
424 // the state moves to a new location due to events (such as .then() or
425 // get_future being called) or due to the promise or future being
426 // moved around.
427 //
428 
429 // non templated base class to reduce code duplication
431  static_assert(sizeof(std::exception_ptr) == sizeof(void*), "exception_ptr not a pointer");
432  enum class state : uintptr_t {
433  invalid = 0,
434  future = 1,
435  // the substate is intended to decouple the run-time prevention
436  // for duplicative result extraction (calling e.g. then() twice
437  // ends up in abandoned()) from the wrapped object's destruction
438  // handling which is orchestrated by future_state. Instead of
439  // creating a temporary future_state just for the sake of setting
440  // the "invalid" in the source instance, result_unavailable can
441  // be set to ensure future_state_base::available() returns false.
442  result_unavailable = 2,
443  result = 3,
444  exception_min = 4, // or anything greater
445  };
446  union any {
447  any() noexcept { st = state::future; }
448  any(state s) noexcept { st = s; }
449  void set_exception(std::exception_ptr&& e) noexcept {
450  new (&ex) std::exception_ptr(std::move(e));
451  assert(st >= state::exception_min);
452  }
453  any(std::exception_ptr&& e) noexcept {
454  set_exception(std::move(e));
455  }
456  // From a users' perspective, a result_unavailable is not valid
457  bool valid() const noexcept { return st != state::invalid && st != state::result_unavailable; }
458  bool available() const noexcept { return st == state::result || st >= state::exception_min; }
459  bool failed() const noexcept { return __builtin_expect(st >= state::exception_min, false); }
460  void check_failure() noexcept;
461  ~any() noexcept { }
462  std::exception_ptr take_exception() noexcept {
463  std::exception_ptr ret(std::move(ex));
464  // Unfortunately in libstdc++ ~exception_ptr is defined out of line. We know that it does nothing for
465  // moved out values, so we omit calling it. This is critical for the code quality produced for this
466  // function. Without the out of line call, gcc can figure out that both sides of the if produce
467  // identical code and merges them.if
468  // We don't make any assumptions about other c++ libraries.
469  // There is request with gcc to define it inline: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90295
470 #ifndef __GLIBCXX__
471  ex.~exception_ptr();
472 #endif
473  st = state::invalid;
474  return ret;
475  }
476  void move_it(any&& x) noexcept {
477 #ifdef __GLIBCXX__
478  // Unfortunally gcc cannot fully optimize the regular
479  // implementation:
480  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95014
481  // Given what we know about the libstdc++ implementation
482  // (see the comment in take_exception), we can just
483  // memmove and zero x. We use memmove to guarantee
484  // vaild results if &x == this.
485  memmove(static_cast<void*>(this), &x, sizeof(any));
486  x.st = state::invalid;
487 #else
488  if (x.st < state::exception_min) {
489  st = x.st;
490  x.st = state::invalid;
491  } else {
492  new (&ex) std::exception_ptr(x.take_exception());
493  }
494 #endif
495  }
496  any(any&& x) noexcept {
497  move_it(std::move(x));
498  }
499  any& operator=(any&& x) noexcept {
500  check_failure();
501  // If this is a self move assignment, check_failure
502  // guarantees that we don't have an exception and calling
503  // move_it is safe.
504  move_it(std::move(x));
505  return *this;
506  }
507  bool has_result() const noexcept {
508  return st == state::result || st == state::result_unavailable;
509  }
510  state st;
511  std::exception_ptr ex;
512  } _u;
513 
514  future_state_base() noexcept = default;
515  future_state_base(state st) noexcept : _u(st) { }
516  future_state_base(std::exception_ptr&& ex) noexcept : _u(std::move(ex)) { }
517  future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
518 
519  // We never need to destruct this polymorphicly, so we can make it
520  // protected instead of virtual.
521 protected:
527  ~future_state_base() noexcept = default;
528 
529  void rethrow_exception() &&;
530  void rethrow_exception() const&;
531 
532 public:
533 
534  bool valid() const noexcept { return _u.valid(); }
535  bool available() const noexcept { return _u.available(); }
536  bool failed() const noexcept { return _u.failed(); }
537 
538  void ignore() noexcept;
539 
540  void set_exception(std::exception_ptr&& ex) noexcept {
541  assert(_u.st == state::future);
542  _u.set_exception(std::move(ex));
543  }
544  future_state_base& operator=(future_state_base&& x) noexcept = default;
545  void set_exception(future_state_base&& state) noexcept {
546  assert(_u.st == state::future);
547  *this = std::move(state);
548  }
549  std::exception_ptr get_exception() && noexcept {
550  assert(_u.st >= state::exception_min);
551  // Move ex out so future::~future() knows we've handled it
552  return _u.take_exception();
553  }
554  const std::exception_ptr& get_exception() const& noexcept {
555  assert(_u.st >= state::exception_min);
556  return _u.ex;
557  }
558  template <typename U>
559  friend struct future_state;
560  template <typename... U>
561  friend future<U...> current_exception_as_future() noexcept;
562  template <typename SEASTAR_ELLIPSIS U>
563  friend class future;
564  template <typename T>
565  friend struct futurize;
566 };
567 
568 void report_failed_future(future_state_base::any&& state) noexcept;
569 
570 inline void future_state_base::any::check_failure() noexcept {
571  if (failed()) {
572  report_failed_future(std::move(*this));
573  }
574 }
575 
579 
581 template <typename T>
582 struct future_state : public future_state_base, private internal::uninitialized_wrapper<T> {
583  static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible<T>::value;
584 #if SEASTAR_API_LEVEL < 5
585  static constexpr bool has_trivial_move_and_destroy = internal::is_tuple_effectively_trivially_move_constructible_and_destructible<T>;
586 #else
587  static constexpr bool has_trivial_move_and_destroy = internal::is_trivially_move_constructible_and_destructible<T>::value;
588 #endif
589  static_assert(std::is_nothrow_move_constructible<T>::value,
590  "Types must be no-throw move constructible");
591  static_assert(std::is_nothrow_destructible<T>::value,
592  "Types must be no-throw destructible");
593  future_state() noexcept = default;
594  void move_it(future_state&& x) noexcept {
595  if constexpr (has_trivial_move_and_destroy) {
596 #pragma GCC diagnostic push
597  // This function may copy uninitialized memory, such as when
598  // creating an uninitialized promise and calling get_future()
599  // on it. Gcc 12 started to catch some simple cases of this
600  // at compile time, so we need to tell it that it's fine.
601 #pragma GCC diagnostic ignored "-Wuninitialized"
602  memmove(reinterpret_cast<char*>(&this->uninitialized_get()),
603  &x.uninitialized_get(),
604  internal::used_size<internal::maybe_wrap_ref<T>>::value);
605 #pragma GCC diagnostic pop
606  } else if (_u.has_result()) {
607  this->uninitialized_set(std::move(x.uninitialized_get()));
608  std::destroy_at(&x.uninitialized_get());
609  }
610  }
611 
612  [[gnu::always_inline]]
613  future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
614  move_it(std::move(x));
615  }
616 
617  void clear() noexcept {
618  if (_u.has_result()) {
619  std::destroy_at(&this->uninitialized_get());
620  } else {
621  _u.check_failure();
622  }
623  }
624  __attribute__((always_inline))
625  ~future_state() noexcept {
626  clear();
627  }
628  future_state& operator=(future_state&& x) noexcept {
629  clear();
630  future_state_base::operator=(std::move(x));
631  // If &x == this, _u.st is now state::invalid and so it is
632  // safe to call move_it.
633  move_it(std::move(x));
634  return *this;
635  }
636  template <typename... A>
637  future_state(ready_future_marker, A&&... a) noexcept : future_state_base(state::result) {
638  try {
639  this->uninitialized_set(std::forward<A>(a)...);
640  } catch (...) {
641  new (this) future_state(current_exception_future_marker());
642  }
643  }
644  template <typename... A>
645  void set(A&&... a) noexcept {
646  assert(_u.st == state::future);
647  new (this) future_state(ready_future_marker(), std::forward<A>(a)...);
648  }
649  future_state(exception_future_marker, std::exception_ptr&& ex) noexcept : future_state_base(std::move(ex)) { }
650  future_state(exception_future_marker, future_state_base&& state) noexcept : future_state_base(std::move(state)) { }
651  future_state(current_exception_future_marker m) noexcept : future_state_base(m) { }
652  future_state(nested_exception_marker m, future_state_base&& old) noexcept : future_state_base(m, std::move(old)) { }
653  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)) { }
654  T&& get_value() && noexcept {
655  assert(_u.st == state::result);
656  return static_cast<T&&>(this->uninitialized_get());
657  }
658  T&& take_value() && noexcept {
659  assert(_u.st == state::result);
660  _u.st = state::result_unavailable;
661  return static_cast<T&&>(this->uninitialized_get());
662  }
663  template<typename U = T>
664  const std::enable_if_t<std::is_copy_constructible<U>::value, U>& get_value() const& noexcept(copy_noexcept) {
665  assert(_u.st == state::result);
666  return this->uninitialized_get();
667  }
668  T&& take() && {
669  assert(available());
670  if (_u.st >= state::exception_min) {
671  std::move(*this).rethrow_exception();
672  }
673  _u.st = state::result_unavailable;
674  return static_cast<T&&>(this->uninitialized_get());
675  }
676  T&& get() && {
677  assert(available());
678  if (_u.st >= state::exception_min) {
679  std::move(*this).rethrow_exception();
680  }
681  return static_cast<T&&>(this->uninitialized_get());
682  }
683  const T& get() const& {
684  assert(available());
685  if (_u.st >= state::exception_min) {
686  rethrow_exception();
687  }
688  return this->uninitialized_get();
689  }
690  using get0_return_type = typename internal::get0_return_type<internal::future_tuple_type_t<T>>::type;
691  static get0_return_type get0(T&& x) {
692  return internal::get0_return_type<T>::get0(std::move(x));
693  }
694 
695  get0_return_type get0() {
696 #if SEASTAR_API_LEVEL < 5
697  return get0(std::move(*this).get());
698 #else
699  return std::move(*this).get();
700 #endif
701  }
702 };
703 
704 #if SEASTAR_API_LEVEL < 6
705 template <typename... T>
706 #else
707 template <typename T = void>
708 #endif
709 class continuation_base : public task {
710 protected:
711  using future_state = seastar::future_state<internal::future_stored_type_t<T SEASTAR_ELLIPSIS>>;
712  future_state _state;
713  using future_type = future<T SEASTAR_ELLIPSIS>;
714  using promise_type = promise<T SEASTAR_ELLIPSIS>;
715 public:
716  continuation_base() noexcept = default;
717  void set_state(future_state&& state) noexcept {
718  _state = std::move(state);
719  }
720  // This override of waiting_task() is needed here because there are cases
721  // when backtrace is obtained from the destructor of this class and objects
722  // of derived classes are already destroyed at that time. If we didn't
723  // have this override we would get a "pure virtual function call" exception.
724  virtual task* waiting_task() noexcept override { return nullptr; }
725  friend class internal::promise_base_with_type<T SEASTAR_ELLIPSIS>;
726  friend class promise<T SEASTAR_ELLIPSIS>;
727  friend class future<T SEASTAR_ELLIPSIS>;
728 };
729 
730 // Given a future type, find the corresponding continuation_base.
731 template <typename Future>
732 struct continuation_base_from_future;
733 
734 template <typename... T>
735 struct continuation_base_from_future<future<T...>> {
736  using type = continuation_base<T...>;
737 };
738 
739 template <typename Future>
740 using continuation_base_from_future_t = typename continuation_base_from_future<Future>::type;
741 
742 #if SEASTAR_API_LEVEL < 6
743 template <typename Promise, typename... T>
744 #else
745 template <typename Promise, typename T = void>
746 #endif
747 class continuation_base_with_promise : public continuation_base<T SEASTAR_ELLIPSIS> {
748  friend class internal::promise_base_with_type<T SEASTAR_ELLIPSIS>;
749 protected:
750  continuation_base_with_promise(Promise&& pr) noexcept : _pr(std::move(pr)) {
751  task::make_backtrace();
752  }
753  virtual task* waiting_task() noexcept override;
754  Promise _pr;
755 };
756 
757 #if SEASTAR_API_LEVEL < 6
758 template <typename Promise, typename Func, typename Wrapper, typename... T>
759 #else
760 template <typename Promise, typename Func, typename Wrapper, typename T = void>
761 #endif
762 struct continuation final : continuation_base_with_promise<Promise, T SEASTAR_ELLIPSIS> {
763  // Func is the original function passed to then/then_wrapped. The
764  // Wrapper is a helper function that implements the specific logic
765  // needed by then/then_wrapped. We call the wrapper passing it the
766  // original function, promise and state.
767  // Note that if Func's move constructor throws, this will call
768  // std::unexpected. We could try to require Func to be nothrow
769  // move constructible, but that will cause a lot of churn. Since
770  // we can't support a failure to create a continuation, calling
771  // std::unexpected as close to the failure as possible is the best
772  // we can do.
773  continuation(Promise&& pr, Func&& func, Wrapper&& wrapper) noexcept
774  : continuation_base_with_promise<Promise, T SEASTAR_ELLIPSIS>(std::move(pr))
775  , _func(std::move(func))
776  , _wrapper(std::move(wrapper)) {}
777  virtual void run_and_dispose() noexcept override {
778  try {
779  _wrapper(std::move(this->_pr), _func, std::move(this->_state));
780  } catch (...) {
781  this->_pr.set_to_current_exception();
782  }
783  delete this;
784  }
785  Func _func;
786  [[no_unique_address]] Wrapper _wrapper;
787 };
788 
789 #if SEASTAR_API_LEVEL < 4
790 
791 // This is an internal future<> payload for seastar::when_all_succeed(). It is used
792 // to return a variadic future (when two or more of its input futures were non-void),
793 // but with variadic futures deprecated and soon gone this is no longer possible.
794 //
795 // Instead, we use this tuple type, and future::then() knows to unpack it.
796 //
797 // The whole thing is temporary for a transition period.
798 template <typename... T>
799 struct when_all_succeed_tuple : std::tuple<T...> {
800  using std::tuple<T...>::tuple;
801  when_all_succeed_tuple(std::tuple<T...>&& t)
802  noexcept(std::is_nothrow_move_constructible<std::tuple<T...>>::value)
803  : std::tuple<T...>(std::move(t)) {}
804 };
805 
806 #endif
807 
808 namespace internal {
809 
810 template <typename... T>
811 future<T...> make_exception_future(future_state_base&& state) noexcept;
812 
813 template <typename... T, typename U>
814 void set_callback(future<T...>&& fut, U* callback) noexcept;
815 
816 class future_base;
817 
818 class promise_base {
819 protected:
820  enum class urgent { no, yes };
821  future_base* _future = nullptr;
822 
823  // This points to the future_state that is currently being
824  // used. See comment above the future_state struct definition for
825  // details.
826  future_state_base* _state;
827 
828  task* _task = nullptr;
829 
830  promise_base(const promise_base&) = delete;
831  promise_base(future_state_base* state) noexcept : _state(state) {}
832  promise_base(future_base* future, future_state_base* state) noexcept;
833  void move_it(promise_base&& x) noexcept;
834  promise_base(promise_base&& x) noexcept;
835 
836  void clear() noexcept;
837 
838  // We never need to destruct this polymorphicly, so we can make it
839  // protected instead of virtual
840  ~promise_base() noexcept {
841  clear();
842  }
843 
844  void operator=(const promise_base&) = delete;
845  promise_base& operator=(promise_base&& x) noexcept;
846 
847  template<urgent Urgent>
848  void make_ready() noexcept;
849 
850  template<typename T>
851  void set_exception_impl(T&& val) noexcept {
852  if (_state) {
853  _state->set_exception(std::move(val));
854  make_ready<urgent::no>();
855  } else {
856  // We get here if promise::get_future is called and the
857  // returned future is destroyed without creating a
858  // continuation.
859  // In older versions of seastar we would store a local
860  // copy of ex and warn in the promise destructor.
861  // Since there isn't any way for the user to clear
862  // the exception, we issue the warning from here.
863  report_failed_future(val);
864  }
865  }
866 
867  void set_exception(future_state_base&& state) noexcept {
868  set_exception_impl(std::move(state));
869  }
870 
871  void set_exception(std::exception_ptr&& ex) noexcept {
872  set_exception_impl(std::move(ex));
873  }
874 
875  void set_exception(const std::exception_ptr& ex) noexcept {
876  set_exception(std::exception_ptr(ex));
877  }
878 
879  template<typename Exception>
880  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
881  set_exception(std::make_exception_ptr(std::forward<Exception>(e)));
882  }
883 
884  friend class future_base;
885  template <typename SEASTAR_ELLIPSIS U> friend class seastar::future;
886 
887 public:
892  void set_to_current_exception() noexcept;
893 
895  task* waiting_task() const noexcept { return _task; }
896 };
897 
904 template <typename SEASTAR_ELLIPSIS T>
905 class promise_base_with_type : protected internal::promise_base {
906 protected:
907  using future_state = seastar::future_state<future_stored_type_t<T SEASTAR_ELLIPSIS>>;
908  future_state* get_state() noexcept {
909  return static_cast<future_state*>(_state);
910  }
911  static constexpr bool copy_noexcept = future_state::copy_noexcept;
912 public:
913  promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
914  promise_base_with_type(future<T SEASTAR_ELLIPSIS>* future) noexcept : promise_base(future, &future->_state) { }
915  promise_base_with_type(promise_base_with_type&& x) noexcept = default;
916  promise_base_with_type(const promise_base_with_type&) = delete;
917  promise_base_with_type& operator=(promise_base_with_type&& x) noexcept = default;
918  void operator=(const promise_base_with_type&) = delete;
919 
920  void set_urgent_state(future_state&& state) noexcept {
921  auto* ptr = get_state();
922  // The state can be null if the corresponding future has been
923  // destroyed without producing a continuation.
924  if (ptr) {
925  // FIXME: This is a fairly expensive assert. It would be a
926  // good candidate for being disabled in release builds if
927  // we had such an assert.
928  assert(ptr->_u.st == future_state_base::state::future);
929  new (ptr) future_state(std::move(state));
930  make_ready<urgent::yes>();
931  }
932  }
933 
934  template <typename... A>
935  void set_value(A&&... a) noexcept {
936  if (auto *s = get_state()) {
937  s->set(std::forward<A>(a)...);
938  make_ready<urgent::no>();
939  }
940  }
941 
946  void set_to_current_exception() noexcept {
947  internal::promise_base::set_to_current_exception();
948  }
949 
951  using internal::promise_base::waiting_task;
952 
953 private:
954 
955  template <typename SEASTAR_ELLIPSIS U>
956  friend class seastar::future;
957 
958  friend future_state;
959 };
960 }
962 
968 template <typename SEASTAR_ELLIPSIS T>
969 class promise : private internal::promise_base_with_type<T SEASTAR_ELLIPSIS> {
970  using future_state = typename internal::promise_base_with_type<T SEASTAR_ELLIPSIS>::future_state;
971  future_state _local_state;
972 
973 public:
977  promise() noexcept : internal::promise_base_with_type<T SEASTAR_ELLIPSIS>(&_local_state) {}
978 
980  void move_it(promise&& x) noexcept;
981  promise(promise&& x) noexcept : internal::promise_base_with_type<T SEASTAR_ELLIPSIS>(std::move(x)) {
982  move_it(std::move(x));
983  }
984  promise(const promise&) = delete;
985  promise& operator=(promise&& x) noexcept {
986  internal::promise_base_with_type<T SEASTAR_ELLIPSIS>::operator=(std::move(x));
987  // If this is a self-move, _state is now nullptr and it is
988  // safe to call move_it.
989  move_it(std::move(x));
990  return *this;
991  }
992  void operator=(const promise&) = delete;
993 
998  void set_to_current_exception() noexcept {
999  internal::promise_base::set_to_current_exception();
1000  }
1001 
1003  using internal::promise_base::waiting_task;
1004 
1012 
1024  template <typename... A>
1025  void set_value(A&&... a) noexcept {
1026  internal::promise_base_with_type<T SEASTAR_ELLIPSIS>::set_value(std::forward<A>(a)...);
1027  }
1028 
1033  void set_exception(std::exception_ptr&& ex) noexcept {
1034  internal::promise_base::set_exception(std::move(ex));
1035  }
1036 
1037  void set_exception(const std::exception_ptr& ex) noexcept {
1038  internal::promise_base::set_exception(ex);
1039  }
1040 
1045  template<typename Exception>
1046  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
1047  internal::promise_base::set_exception(std::forward<Exception>(e));
1048  }
1049 
1050  using internal::promise_base_with_type<T SEASTAR_ELLIPSIS>::set_urgent_state;
1051 
1052  template <typename SEASTAR_ELLIPSIS U>
1053  friend class future;
1054 };
1055 
1056 #if SEASTAR_API_LEVEL < 6
1062 template<>
1063 class promise<void> : public promise<> {};
1064 #endif
1065 
1067 
1070 
1071 
1077 template <typename... T> struct is_future : std::false_type {};
1078 
1081 template <typename... T> struct is_future<future<T...>> : std::true_type {};
1082 
1084 
1085 
1089 template <typename T>
1090 struct futurize;
1091 
1092 SEASTAR_CONCEPT(
1093 
1094 template <typename T>
1095 concept Future = is_future<T>::value;
1096 
1097 template <typename Func, typename... T>
1098 concept CanInvoke = std::invocable<Func, T...>;
1099 
1100 // Deprecated alias
1101 template <typename Func, typename... T>
1102 concept CanApply = CanInvoke<Func, T...>;
1103 
1104 template <typename Func, typename... T>
1105 concept CanApplyTuple
1106  = sizeof...(T) == 1
1107  && requires (Func func, std::tuple<T...> wrapped_val) {
1108  { std::apply(func, std::get<0>(std::move(wrapped_val))) };
1109  };
1110 
1111 template <typename Func, typename Return, typename... T>
1112 concept InvokeReturns = requires (Func f, T... args) {
1113  { f(std::forward<T>(args)...) } -> std::same_as<Return>;
1114 };
1115 
1116 // Deprecated alias
1117 template <typename Func, typename Return, typename... T>
1118 concept ApplyReturns = InvokeReturns<Func, Return, T...>;
1119 
1120 template <typename Func, typename... T>
1121 concept InvokeReturnsAnyFuture = Future<std::invoke_result_t<Func, T...>>;
1122 
1123 // Deprecated alias
1124 template <typename Func, typename... T>
1125 concept ApplyReturnsAnyFuture = InvokeReturnsAnyFuture<Func, T...>;
1126 
1127 )
1128 
1130 
1131 // Converts a type to a future type, if it isn't already.
1132 template <typename T>
1133 using futurize_t = typename futurize<T>::type;
1134 
1136 
1137 template<typename Func, typename... Args>
1138 auto futurize_invoke(Func&& func, Args&&... args) noexcept;
1139 
1140 template<typename Func, typename... Args>
1141 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept;
1142 
1145 namespace internal {
1146 class future_base {
1147 protected:
1148  promise_base* _promise;
1149  future_base() noexcept : _promise(nullptr) {}
1150  future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
1151  _promise->_future = this;
1152  _promise->_state = state;
1153  }
1154 
1155  void move_it(future_base&& x, future_state_base* state) noexcept {
1156  _promise = x._promise;
1157  if (auto* p = _promise) {
1158  x.detach_promise();
1159  p->_future = this;
1160  p->_state = state;
1161  }
1162  }
1163 
1164  future_base(future_base&& x, future_state_base* state) noexcept {
1165  move_it(std::move(x), state);
1166  }
1167 
1168  void clear() noexcept {
1169  if (_promise) {
1170  detach_promise();
1171  }
1172  }
1173 
1174  ~future_base() noexcept {
1175  clear();
1176  }
1177 
1178  promise_base* detach_promise() noexcept {
1179  _promise->_state = nullptr;
1180  _promise->_future = nullptr;
1181  return std::exchange(_promise, nullptr);
1182  }
1183 
1184  void schedule(task* tws, future_state_base* state) noexcept {
1185  promise_base* p = detach_promise();
1186  p->_state = state;
1187  p->_task = tws;
1188  }
1189 
1190  void do_wait() noexcept;
1191 
1192 #ifdef SEASTAR_COROUTINES_ENABLED
1193  void set_coroutine(task& coroutine) noexcept;
1194 #endif
1195 
1196  friend class promise_base;
1197 };
1198 
1199 template <typename Func, typename... T>
1200 struct future_result {
1201  using type = std::invoke_result_t<Func, T...>;
1202  using future_type = futurize_t<type>;
1203  using func_type = future_type (T&&...);
1204 };
1205 
1206 template <typename Func>
1207 struct future_result<Func, void> {
1208  using type = std::invoke_result_t<Func>;
1209  using future_type = futurize_t<type>;
1210  using func_type = future_type ();
1211 };
1212 
1213 template <typename Func, typename SEASTAR_ELLIPSIS T>
1214 using future_result_t = typename future_result<Func, T SEASTAR_ELLIPSIS>::type;
1215 
1216 template <typename Func, typename T>
1217 auto future_invoke(Func&& func, T&& v) {
1218  if constexpr (std::is_same_v<T, monostate>) {
1219  return std::invoke(std::forward<Func>(func));
1220  } else {
1221  return std::invoke(std::forward<Func>(func), std::forward<T>(v));
1222  }
1223 }
1224 
1225 // This is a customization point for future::then()'s implementation.
1226 // It behaves differently when the future value type is a when_all_succeed_tuple
1227 // instantiation, indicating we need to unpack the tuple into multiple lambda
1228 // arguments.
1229 template <typename Future>
1230 struct call_then_impl;
1231 
1232 // Generic case - the input is not a future<when_all_succeed_tuple<...>>, so
1233 // we just forward everything to future::then_impl.
1234 template <typename... T>
1235 struct call_then_impl<future<T...>> {
1236  template <typename Func>
1237  using result_type = typename future_result<Func, T...>::future_type;
1238 
1239  template <typename Func>
1240  using func_type = typename future_result<Func, T...>::func_type;
1241 
1242  template <typename Func>
1243  static result_type<Func> run(future<T...>& fut, Func&& func) noexcept {
1244  return fut.then_impl(std::forward<Func>(func));
1245  }
1246 };
1247 
1248 #if SEASTAR_API_LEVEL < 4
1249 
1250 // Special case: we unpack the tuple before calling the function
1251 template <typename... T>
1252 struct call_then_impl<future<when_all_succeed_tuple<T...>>> {
1253  template <typename Func>
1254  using result_type = futurize_t<std::invoke_result_t<Func, T&&...>>;
1255 
1256  template <typename Func>
1257  using func_type = result_type<Func> (T&&...);
1258 
1259  using was_tuple = when_all_succeed_tuple<T...>;
1260  using std_tuple = std::tuple<T...>;
1261 
1262  template <typename Func>
1263  static auto run(future<was_tuple>& fut, Func&& func) noexcept {
1264  // constructing func in the lambda can throw, but there's nothing we can do
1265  // about it, similar to #84.
1266  return fut.then_impl([func = std::forward<Func>(func)] (was_tuple&& t) mutable {
1267  return std::apply(func, static_cast<std_tuple&&>(std::move(t)));
1268  });
1269  }
1270 };
1271 
1272 #endif
1273 
1274 template <typename Func, typename... Args>
1275 using call_then_impl_result_type = typename call_then_impl<future<Args...>>::template result_type<Func>;
1276 
1277 SEASTAR_CONCEPT(
1278 template <typename Func, typename... Args>
1279 concept CanInvokeWhenAllSucceed = requires {
1280  typename call_then_impl_result_type<Func, Args...>;
1281 };
1282 )
1283 
1284 template <typename Func, typename... T>
1285 struct result_of_apply {
1286  // no "type" member if not a function call signature or not a tuple
1287 };
1288 
1289 template <typename Func, typename... T>
1290 struct result_of_apply<Func, std::tuple<T...>> : std::invoke_result<Func, T...> {
1291  // Let std::invoke_result_t determine the result if the input is a tuple
1292 };
1293 
1294 template <typename Func, typename... T>
1295 using result_of_apply_t = typename result_of_apply<Func, T...>::type;
1296 
1297 }
1298 
1299 template <typename Promise, typename SEASTAR_ELLIPSIS T>
1300 task* continuation_base_with_promise<Promise, T SEASTAR_ELLIPSIS>::waiting_task() noexcept {
1301  return _pr.waiting_task();
1302 }
1303 
1346 template <typename SEASTAR_ELLIPSIS T>
1347 class [[nodiscard]] future : private internal::future_base {
1348  using future_state = seastar::future_state<internal::future_stored_type_t<T SEASTAR_ELLIPSIS>>;
1349  future_state _state;
1350  static constexpr bool copy_noexcept = future_state::copy_noexcept;
1351  using call_then_impl = internal::call_then_impl<future>;
1352 
1353 private:
1354  // This constructor creates a future that is not ready but has no
1355  // associated promise yet. The use case is to have a less flexible
1356  // but more efficient future/promise pair where we know that
1357  // promise::set_value cannot possibly be called without a matching
1358  // future and so that promise doesn't need to store a
1359  // future_state.
1361 
1362  future(promise<T SEASTAR_ELLIPSIS>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
1363  template <typename... A>
1364  future(ready_future_marker m, A&&... a) noexcept : _state(m, std::forward<A>(a)...) { }
1366  future(future_state_base::nested_exception_marker m, future_state_base&& old) noexcept : _state(m, std::move(old)) {}
1367  future(future_state_base::nested_exception_marker m, future_state_base&& n, future_state_base&& old) noexcept : _state(m, std::move(n), std::move(old)) {}
1368  future(exception_future_marker m, std::exception_ptr&& ex) noexcept : _state(m, std::move(ex)) { }
1369  future(exception_future_marker m, future_state_base&& state) noexcept : _state(m, std::move(state)) { }
1370  [[gnu::always_inline]]
1371  explicit future(future_state&& state) noexcept
1372  : _state(std::move(state)) {
1373  }
1374  internal::promise_base_with_type<T SEASTAR_ELLIPSIS> get_promise() noexcept {
1375  assert(!_promise);
1376  return internal::promise_base_with_type<T SEASTAR_ELLIPSIS>(this);
1377  }
1378  internal::promise_base_with_type<T SEASTAR_ELLIPSIS>* detach_promise() noexcept {
1379  return static_cast<internal::promise_base_with_type<T SEASTAR_ELLIPSIS>*>(future_base::detach_promise());
1380  }
1381  void schedule(continuation_base<T SEASTAR_ELLIPSIS>* tws) noexcept {
1382  future_base::schedule(tws, &tws->_state);
1383  }
1384  template <typename Pr, typename Func, typename Wrapper>
1385  void schedule(Pr&& pr, Func&& func, Wrapper&& wrapper) noexcept {
1386  // If this new throws a std::bad_alloc there is nothing that
1387  // can be done about it. The corresponding future is not ready
1388  // and we cannot break the chain. Since this function is
1389  // noexcept, it will call std::terminate if new throws.
1391  auto tws = new continuation<Pr, Func, Wrapper, T SEASTAR_ELLIPSIS>(std::move(pr), std::move(func), std::move(wrapper));
1392  // In a debug build we schedule ready futures, but not in
1393  // other build modes.
1394 #ifdef SEASTAR_DEBUG
1395  if (_state.available()) {
1396  tws->set_state(get_available_state_ref());
1397  ::seastar::schedule(tws);
1398  return;
1399  }
1400 #endif
1401  schedule(tws);
1402  _state._u.st = future_state_base::state::invalid;
1403  }
1404 
1405  [[gnu::always_inline]]
1406  future_state&& get_available_state_ref() noexcept {
1407  if (_promise) {
1408  detach_promise();
1409  }
1410  return std::move(_state);
1411  }
1412 
1413  future<T SEASTAR_ELLIPSIS> rethrow_with_nested(future_state_base&& n) noexcept {
1414  return future<T SEASTAR_ELLIPSIS>(future_state_base::nested_exception_marker(), std::move(n), std::move(_state));
1415  }
1416 
1417  future<T SEASTAR_ELLIPSIS> rethrow_with_nested() noexcept {
1419  }
1420 
1421  template<typename... U>
1422  friend class shared_future;
1423 public:
1425  using value_type = internal::future_stored_type_t<T SEASTAR_ELLIPSIS>;
1426  using tuple_type = internal::future_tuple_type_t<value_type>;
1430  [[gnu::always_inline]]
1431  future(future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1432  future(const future&) = delete;
1433  future& operator=(future&& x) noexcept {
1434  clear();
1435  move_it(std::move(x), &_state);
1436  _state = std::move(x._state);
1437  return *this;
1438  }
1439  void operator=(const future&) = delete;
1449  [[gnu::always_inline]]
1451  wait();
1452  return get_available_state_ref().take();
1453  }
1454 
1455  [[gnu::always_inline]]
1456  std::exception_ptr get_exception() noexcept {
1457  return get_available_state_ref().get_exception();
1458  }
1459 
1468  using get0_return_type = typename future_state::get0_return_type;
1469  get0_return_type get0() {
1470 #if SEASTAR_API_LEVEL < 5
1471  return future_state::get0(get());
1472 #else
1473  return (get0_return_type)get();
1474 #endif
1475  }
1476 
1482  void wait() noexcept {
1483  if (_state.available()) {
1484  return;
1485  }
1486  do_wait();
1487  }
1488 
1492  [[gnu::always_inline]]
1493  bool available() const noexcept {
1494  return _state.available();
1495  }
1496 
1500  [[gnu::always_inline]]
1501  bool failed() const noexcept {
1502  return _state.failed();
1503  }
1504 
1520  template <typename Func, typename Result = futurize_t<typename call_then_impl::template result_type<Func>>>
1521  SEASTAR_CONCEPT( requires std::invocable<Func, T SEASTAR_ELLIPSIS> || internal::CanInvokeWhenAllSucceed<Func, T SEASTAR_ELLIPSIS>)
1522  Result
1523  then(Func&& func) noexcept {
1524  // The implementation of then() is customized via the call_then_impl helper
1525  // template, in order to special case the results of when_all_succeed().
1526  // when_all_succeed() used to return a variadic future, which is deprecated, so
1527  // now it returns a when_all_succeed_tuple, which we intercept in call_then_impl,
1528  // and treat it as a variadic future.
1529 #ifndef SEASTAR_TYPE_ERASE_MORE
1530  return call_then_impl::run(*this, std::move(func));
1531 #else
1532  using func_type = typename call_then_impl::template func_type<Func>;
1534  {
1536  ncf = noncopyable_function<func_type>([func = std::forward<Func>(func)](auto&&... args) mutable {
1537  return futurize_invoke(func, std::forward<decltype(args)>(args)...);
1538  });
1539  }
1540  return call_then_impl::run(*this, std::move(ncf));
1541 #endif
1542  }
1543 
1563  template <typename Func, typename Result = futurize_t<internal::result_of_apply_t<Func, T SEASTAR_ELLIPSIS>>>
1564  SEASTAR_CONCEPT( requires ::seastar::CanApplyTuple<Func, T SEASTAR_ELLIPSIS>)
1565  Result
1566  then_unpack(Func&& func) noexcept {
1567  return then([func = std::forward<Func>(func)] (T&& SEASTAR_ELLIPSIS tuple) mutable {
1568  // sizeof...(tuple) is required to be 1
1569  return std::apply(func, std::move(tuple) SEASTAR_ELLIPSIS);
1570  });
1571  }
1572 
1573 private:
1574 
1575  // Keep this simple so that Named Return Value Optimization is used.
1576  template <typename Func, typename Result>
1577  Result then_impl_nrvo(Func&& func) noexcept {
1579  typename futurator::type fut(future_for_get_promise_marker{});
1580  using pr_type = decltype(fut.get_promise());
1581  schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1582  if (state.failed()) {
1583  pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1584  } else {
1585  futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1586 #if SEASTAR_API_LEVEL < 5
1587  return std::apply(func, std::move(state).get_value());
1588 #else
1589  // clang thinks that "state" is not used, below, for future<>.
1590  // Make it think it is used to avoid an unused-lambda-capture warning.
1591  (void)state;
1592  return internal::future_invoke(func, std::move(state).get_value());
1593 #endif
1594  });
1595  }
1596  });
1597  return fut;
1598  }
1599 
1600  template <typename Func, typename Result = futurize_t<internal::future_result_t<Func, T SEASTAR_ELLIPSIS>>>
1601  Result
1602  then_impl(Func&& func) noexcept {
1603 #ifndef SEASTAR_DEBUG
1604  using futurator = futurize<internal::future_result_t<Func, T SEASTAR_ELLIPSIS>>;
1605  if (failed()) {
1606  return futurator::make_exception_future(static_cast<future_state_base&&>(get_available_state_ref()));
1607  } else if (available()) {
1608 #if SEASTAR_API_LEVEL < 5
1609  return futurator::apply(std::forward<Func>(func), get_available_state_ref().take_value());
1610 #else
1611  return futurator::invoke(std::forward<Func>(func), get_available_state_ref().take_value());
1612 #endif
1613  }
1614 #endif
1615  return then_impl_nrvo<Func, Result>(std::forward<Func>(func));
1616  }
1617 
1618 public:
1634  template <typename Func, typename FuncResult = std::invoke_result_t<Func, future>>
1635  SEASTAR_CONCEPT( requires std::invocable<Func, future> )
1636  futurize_t<FuncResult>
1637  then_wrapped(Func&& func) & noexcept {
1638  return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1639  }
1640 
1641  template <typename Func, typename FuncResult = std::invoke_result_t<Func, future&&>>
1642  SEASTAR_CONCEPT( requires std::invocable<Func, future&&> )
1643  futurize_t<FuncResult>
1644  then_wrapped(Func&& func) && noexcept {
1645  return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1646  }
1647 
1648 private:
1649 
1650  template <bool AsSelf, typename FuncResult, typename Func>
1651  futurize_t<FuncResult>
1652  then_wrapped_maybe_erase(Func&& func) noexcept {
1653 #ifndef SEASTAR_TYPE_ERASE_MORE
1654  return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1655 #else
1656  using futurator = futurize<FuncResult>;
1657  using WrapFuncResult = typename futurator::type;
1658  noncopyable_function<WrapFuncResult (future&&)> ncf;
1659  {
1660  memory::scoped_critical_alloc_section _;
1661  ncf = noncopyable_function<WrapFuncResult(future &&)>([func = std::forward<Func>(func)](future&& f) mutable {
1662  return futurator::invoke(func, std::move(f));
1663  });
1664  }
1665  return then_wrapped_common<AsSelf, WrapFuncResult>(std::move(ncf));
1666 #endif
1667  }
1668 
1669  // Keep this simple so that Named Return Value Optimization is used.
1670  template <typename FuncResult, typename Func>
1671  futurize_t<FuncResult>
1672  then_wrapped_nrvo(Func&& func) noexcept {
1673  using futurator = futurize<FuncResult>;
1674  typename futurator::type fut(future_for_get_promise_marker{});
1675  using pr_type = decltype(fut.get_promise());
1676  schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1677  futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1678  return func(future(std::move(state)));
1679  });
1680  });
1681  return fut;
1682  }
1683 
1684 
1685  template <bool AsSelf, typename FuncResult, typename Func>
1686  futurize_t<FuncResult>
1687  then_wrapped_common(Func&& func) noexcept {
1688 #ifndef SEASTAR_DEBUG
1689  using futurator = futurize<FuncResult>;
1690  if (available()) {
1691  if constexpr (AsSelf) {
1692  if (_promise) {
1693  detach_promise();
1694  }
1695  return futurator::invoke(std::forward<Func>(func), std::move(*this));
1696  } else {
1697  return futurator::invoke(std::forward<Func>(func), future(get_available_state_ref()));
1698  }
1699  }
1700 #endif
1701  return then_wrapped_nrvo<FuncResult, Func>(std::forward<Func>(func));
1702  }
1703 
1704  void forward_to(internal::promise_base_with_type<T SEASTAR_ELLIPSIS>&& pr) noexcept {
1705  if (_state.available()) {
1706  pr.set_urgent_state(std::move(_state));
1707  } else {
1708  *detach_promise() = std::move(pr);
1709  }
1710  }
1711 
1712 public:
1724  if (_state.available()) {
1725  pr.set_urgent_state(std::move(_state));
1726  } else if (&pr._local_state != pr._state) {
1727  // The only case when _state points to _local_state is
1728  // when get_future was never called. Given that pr will
1729  // soon be destroyed, we know get_future will never be
1730  // called and we can just ignore this request.
1731  *detach_promise() = std::move(pr);
1732  }
1733  }
1734 
1735 
1736 
1752  template <typename Func>
1753  SEASTAR_CONCEPT( requires std::invocable<Func> )
1754  future<T SEASTAR_ELLIPSIS> finally(Func&& func) noexcept {
1755  return then_wrapped(finally_body<Func, is_future<std::invoke_result_t<Func>>::value>(std::forward<Func>(func)));
1756  }
1757 
1758 
1759  template <typename Func, bool FuncReturnsFuture>
1761 
1762  template <typename Func>
1763  struct finally_body<Func, true> {
1764  Func _func;
1765 
1766  finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1767  { }
1768 
1769  future<T SEASTAR_ELLIPSIS> operator()(future<T SEASTAR_ELLIPSIS>&& result) noexcept {
1770  return futurize_invoke(_func).then_wrapped([result = std::move(result)](auto&& f_res) mutable {
1771  if (!f_res.failed()) {
1772  return std::move(result);
1773  } else {
1774  return result.rethrow_with_nested(std::move(f_res._state));
1775  }
1776  });
1777  }
1778  };
1779 
1780  template <typename Func>
1781  struct finally_body<Func, false> {
1782  Func _func;
1783 
1784  finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1785  { }
1786 
1787  future<T SEASTAR_ELLIPSIS> operator()(future<T SEASTAR_ELLIPSIS>&& result) noexcept {
1788  try {
1789  _func();
1790  return std::move(result);
1791  } catch (...) {
1792  return result.rethrow_with_nested();
1793  }
1794  };
1795  };
1796 
1801  future<> or_terminate() noexcept {
1802  return then_wrapped([] (auto&& f) {
1803  try {
1804  f.get();
1805  } catch (...) {
1806  engine_exit(std::current_exception());
1807  }
1808  });
1809  }
1810 
1816  // We need the generic variadic lambda, below, because then() behaves differently
1817  // when value_type is when_all_succeed_tuple
1818  return then([] (auto&&...) {});
1819  }
1820 
1834  template <typename Func>
1835  SEASTAR_CONCEPT( requires ::seastar::InvokeReturns<Func, future<T SEASTAR_ELLIPSIS>, std::exception_ptr>
1836  || (std::tuple_size_v<tuple_type> == 0 && ::seastar::InvokeReturns<Func, void, std::exception_ptr>)
1837  || (std::tuple_size_v<tuple_type> == 1 && ::seastar::InvokeReturns<Func, T, std::exception_ptr>)
1838  || (std::tuple_size_v<tuple_type> > 1 && ::seastar::InvokeReturns<Func, tuple_type, std::exception_ptr>)
1839  )
1840  future<T SEASTAR_ELLIPSIS> handle_exception(Func&& func) noexcept {
1841  return then_wrapped([func = std::forward<Func>(func)]
1842  (auto&& fut) mutable -> future<T SEASTAR_ELLIPSIS> {
1843  if (!fut.failed()) {
1844  return make_ready_future<T SEASTAR_ELLIPSIS>(fut.get());
1845  } else {
1846  return futurize_invoke(func, fut.get_exception());
1847  }
1848  });
1849  }
1850 
1861  template <typename Func>
1863  using trait = function_traits<Func>;
1864  static_assert(trait::arity == 1, "func can take only one parameter");
1865  using ex_type = typename trait::template arg<0>::type;
1866  return then_wrapped([func = std::forward<Func>(func)]
1867  (auto&& fut) mutable -> future<T SEASTAR_ELLIPSIS> {
1868  try {
1869  return make_ready_future<T SEASTAR_ELLIPSIS>(fut.get());
1870  } catch(ex_type& ex) {
1871  return futurize_invoke(func, ex);
1872  }
1873  });
1874  }
1875 
1881  void ignore_ready_future() noexcept {
1882  _state.ignore();
1883  }
1884 
1885 #ifdef SEASTAR_COROUTINES_ENABLED
1886  using future_base::set_coroutine;
1887 #endif
1888 private:
1889  void set_callback(continuation_base<T SEASTAR_ELLIPSIS>* callback) noexcept {
1890  if (_state.available()) {
1891  callback->set_state(get_available_state_ref());
1892  ::seastar::schedule(callback);
1893  } else {
1894  assert(_promise);
1895  schedule(callback);
1896  }
1897 
1898  }
1899 
1901  template <typename SEASTAR_ELLIPSIS U>
1902  friend class future;
1903  template <typename SEASTAR_ELLIPSIS U>
1904  friend class promise;
1905  template <typename U>
1906  friend struct futurize;
1907  template <typename SEASTAR_ELLIPSIS U>
1908  friend class internal::promise_base_with_type;
1909  template <typename... U, typename... A>
1910  friend future<U...> make_ready_future(A&&... value) noexcept;
1911  template <typename... U>
1912  friend future<U...> make_exception_future(std::exception_ptr&& ex) noexcept;
1913  template <typename... U, typename Exception>
1914  friend future<U...> make_exception_future(Exception&& ex) noexcept;
1915  template <typename... U>
1916  friend future<U...> internal::make_exception_future(future_state_base&& state) noexcept;
1917  template <typename... U>
1918  friend future<U...> current_exception_as_future() noexcept;
1919  template <typename... U, typename V>
1920  friend void internal::set_callback(future<U...>&&, V*) noexcept;
1921  template <typename Future>
1922  friend struct internal::call_then_impl;
1924 };
1925 
1926 
1927 namespace internal {
1928 template <typename T>
1929 struct futurize_base {
1931  using type = future<T>;
1933  using promise_type = promise<T>;
1934  using promise_base_with_type = internal::promise_base_with_type<T>;
1935 
1937  static inline type convert(T&& value) { return make_ready_future<T>(std::move(value)); }
1938  static inline type convert(type&& value) { return std::move(value); }
1939 
1941  template <typename Arg>
1942  static inline type make_exception_future(Arg&& arg) noexcept;
1943 };
1944 
1945 template <>
1946 struct futurize_base<void> {
1947  using type = future<>;
1948  using promise_type = promise<>;
1949  using promise_base_with_type = internal::promise_base_with_type<>;
1950 
1951  static inline type convert(type&& value) {
1952  return std::move(value);
1953  }
1954  template <typename Arg>
1955  static inline type make_exception_future(Arg&& arg) noexcept;
1956 };
1957 
1958 template <typename T>
1959 struct futurize_base<future<T>> : public futurize_base<T> {};
1960 
1961 template <>
1962 struct futurize_base<future<>> : public futurize_base<void> {};
1963 }
1964 
1965 template <typename T>
1966 struct futurize : public internal::futurize_base<T> {
1967  using base = internal::futurize_base<T>;
1968  using type = typename base::type;
1969  using promise_type = typename base::promise_type;
1970  using promise_base_with_type = typename base::promise_base_with_type;
1972  using value_type = typename type::value_type;
1973  using tuple_type = typename type::tuple_type;
1974  using base::convert;
1976 
1979  template<typename Func, typename... FuncArgs>
1980  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
1981 
1984  template<typename Func, typename... FuncArgs>
1985  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
1986 
1987  template<typename Func>
1988  static inline type invoke(Func&& func, internal::monostate) noexcept {
1989  return invoke(std::forward<Func>(func));
1990  }
1991 
1993  template<typename Func, typename... FuncArgs>
1994  [[deprecated("Use invoke for varargs")]]
1995  static inline type apply(Func&& func, FuncArgs&&... args) noexcept {
1996  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1997  }
1998 
1999  static type current_exception_as_future() noexcept {
2001  }
2002 
2004  static type from_tuple(tuple_type&& value) {
2005  return type(ready_future_marker(), std::move(value));
2006  }
2008  static type from_tuple(const tuple_type& value) {
2009  return type(ready_future_marker(), value);
2010  }
2011 
2012 #if SEASTAR_API_LEVEL >= 5
2014  static type from_tuple(value_type&& value) {
2015  return type(ready_future_marker(), std::move(value));
2016  }
2018  static type from_tuple(const value_type& value) {
2019  return type(ready_future_marker(), value);
2020  }
2021 #endif
2022 private:
2026  template<typename Func>
2027  SEASTAR_CONCEPT( requires std::invocable<Func> )
2028  static void satisfy_with_result_of(promise_base_with_type&&, Func&& func);
2029 
2030  template <typename SEASTAR_ELLIPSIS U>
2031  friend class future;
2032 };
2033 
2034 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
2035  : _future(future), _state(state) {
2036  _future->_promise = this;
2037 }
2038 
2039 template <typename SEASTAR_ELLIPSIS T>
2040 inline
2041 future<T SEASTAR_ELLIPSIS>
2043  assert(!this->_future && this->_state && !this->_task);
2044  return future<T SEASTAR_ELLIPSIS>(this);
2045 }
2046 
2047 template <typename SEASTAR_ELLIPSIS T>
2048 inline
2050  if (this->_state == &x._local_state) {
2051  this->_state = &_local_state;
2052  new (&_local_state) future_state(std::move(x._local_state));
2053  }
2054 }
2055 
2056 template <typename... T, typename... A>
2057 inline
2058 future<T...> make_ready_future(A&&... value) noexcept {
2059  return future<T...>(ready_future_marker(), std::forward<A>(value)...);
2060 }
2061 
2062 template <typename... T>
2063 inline
2064 future<T...> make_exception_future(std::exception_ptr&& ex) noexcept {
2065  return future<T...>(exception_future_marker(), std::move(ex));
2066 }
2067 
2068 template <typename... T>
2069 inline
2070 future<T...> internal::make_exception_future(future_state_base&& state) noexcept {
2071  return future<T...>(exception_future_marker(), std::move(state));
2072 }
2073 
2074 template <typename... T>
2077 }
2078 
2079 void log_exception_trace() noexcept;
2080 
2087 template <typename... T, typename Exception>
2088 inline
2089 future<T...> make_exception_future(Exception&& ex) noexcept {
2090  log_exception_trace();
2091  return make_exception_future<T...>(std::make_exception_ptr(std::forward<Exception>(ex)));
2092 }
2093 
2094 template <typename... T, typename Exception>
2095 future<T...> make_exception_future_with_backtrace(Exception&& ex) noexcept {
2096  return make_exception_future<T...>(make_backtraced_exception_ptr<Exception>(std::forward<Exception>(ex)));
2097 }
2098 
2100 
2102 
2103 template<typename T>
2104 template<typename Func, typename... FuncArgs>
2105 typename futurize<T>::type futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
2106  try {
2107  using ret_t = decltype(std::apply(std::forward<Func>(func), std::move(args)));
2108  if constexpr (std::is_void_v<ret_t>) {
2109  std::apply(std::forward<Func>(func), std::move(args));
2110  return make_ready_future<>();
2111  } else if constexpr (is_future<ret_t>::value){
2112  return std::apply(std::forward<Func>(func), std::move(args));
2113  } else {
2114  return convert(std::apply(std::forward<Func>(func), std::move(args)));
2115  }
2116  } catch (...) {
2117  return current_exception_as_future();
2118  }
2119 }
2120 
2121 template<typename T>
2122 template<typename Func>
2123 SEASTAR_CONCEPT( requires std::invocable<Func> )
2124 void futurize<T>::satisfy_with_result_of(promise_base_with_type&& pr, Func&& func) {
2125  using ret_t = decltype(func());
2126  if constexpr (std::is_void_v<ret_t>) {
2127  func();
2128  pr.set_value();
2129  } else if constexpr (is_future<ret_t>::value) {
2130  func().forward_to(std::move(pr));
2131  } else {
2132  pr.set_value(func());
2133  }
2134 }
2135 
2136 template<typename T>
2137 template<typename Func, typename... FuncArgs>
2138 typename futurize<T>::type futurize<T>::invoke(Func&& func, FuncArgs&&... args) noexcept {
2139  try {
2140  using ret_t = decltype(func(std::forward<FuncArgs>(args)...));
2141  if constexpr (std::is_void_v<ret_t>) {
2142  func(std::forward<FuncArgs>(args)...);
2143  return make_ready_future<>();
2144  } else if constexpr (is_future<ret_t>::value) {
2145  return func(std::forward<FuncArgs>(args)...);
2146  } else {
2147  return convert(func(std::forward<FuncArgs>(args)...));
2148  }
2149  } catch (...) {
2150  return current_exception_as_future();
2151  }
2152 }
2153 
2154 template <typename T>
2155 template <typename Arg>
2156 inline
2157 future<T>
2161  return make_exception_future<T>(std::forward<Arg>(arg));
2162 }
2163 
2164 template <typename Arg>
2165 inline
2166 future<>
2170  return make_exception_future<>(std::forward<Arg>(arg));
2171 }
2172 
2173 template<typename Func, typename... Args>
2174 auto futurize_invoke(Func&& func, Args&&... args) noexcept {
2175  using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2176  return futurator::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2177 }
2178 
2179 template<typename Func, typename... Args>
2180 [[deprecated("Use futurize_invoke for varargs")]]
2181 auto futurize_apply(Func&& func, Args&&... args) noexcept {
2182  return futurize_invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2183 }
2184 
2185 template<typename Func, typename... Args>
2186 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept {
2187  using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2188  return futurator::apply(std::forward<Func>(func), std::move(args));
2189 }
2190 
2191 namespace internal {
2192 
2193 template <typename... T, typename U>
2194 inline
2195 void set_callback(future<T...>&& fut, U* callback) noexcept {
2196  // It would be better to use continuation_base<T...> for U, but
2197  // then a derived class of continuation_base<T...> won't be matched
2198  return std::move(fut).set_callback(callback);
2199 }
2200 
2201 }
2202 
2203 
2205 
2206 }
A representation of a possibly not-yet-computed value.
Definition: future.hh:1347
void wait() noexcept
Definition: future.hh:1482
Result then(Func &&func) noexcept
Schedule a block of code to run when the future is ready.
Definition: future.hh:1523
bool failed() const noexcept
Checks whether the future has failed.
Definition: future.hh:1501
bool available() const noexcept
Checks whether the future is available.
Definition: future.hh:1493
typename future_state::get0_return_type get0_return_type
Definition: future.hh:1468
internal::future_stored_type_t< T > value_type
The data type carried by the future.
Definition: future.hh:1425
future< T > handle_exception_type(Func &&func) noexcept
Handle the exception of a certain type carried by this future.
Definition: future.hh:1862
void forward_to(promise< T > &&pr) noexcept
Satisfy some promise object with this future as a result.
Definition: future.hh:1723
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:1637
Result then_unpack(Func &&func) noexcept
Schedule a block of code to run when the future is ready, unpacking tuples.
Definition: future.hh:1566
future(future &&x) noexcept
Moves the future into a new object.
Definition: future.hh:1431
value_type && get()
gets the value returned by the computation
Definition: future.hh:1450
future discard_result() noexcept
Discards the value carried by this future.
Definition: future.hh:1815
future or_terminate() noexcept
Terminate the program if this future fails.
Definition: future.hh:1801
void ignore_ready_future() noexcept
Ignore any result hold by this future.
Definition: future.hh:1881
Definition: future.hh:1760
promise - allows a future value to be made available at a later time.
Definition: future.hh:969
void set_to_current_exception() noexcept
Definition: future.hh:998
std::enable_if_t<!std::is_same< std::remove_reference_t< Exception >, std::exception_ptr >::value, void > set_exception(Exception &&e) noexcept
Marks the promise as failed.
Definition: future.hh:1046
void set_exception(std::exception_ptr &&ex) noexcept
Marks the promise as failed.
Definition: future.hh:1033
promise() noexcept
Constructs an empty promise.
Definition: future.hh:977
Like future except the result can be waited for by many fibers.
Definition: shared_future.hh:102
future< T... > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:2064
future< T > get_future() noexcept
Gets the promise's associated future.
Definition: future.hh:2042
future< T... > make_exception_future(Exception &&ex) noexcept
Creates a future in an available, failed state.
Definition: future.hh:2089
future< T... > make_ready_future(A &&... value) noexcept
Creates a future in an available, value state.
Definition: future.hh:2058
future< T... > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:2075
void move_it(promise &&x) noexcept
Moves a promise object.
Definition: future.hh:2049
Definition: future.hh:577
Definition: future.hh:576
Definition: critical_alloc_section.hh:80
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
Definition: noncopyable_function.hh:33
Definition: function_traits.hh:62
Exception type for broken promises.
Definition: future.hh:211
Definition: future.hh:430
friend future< U... > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:2075
Converts a type to a future type, if it isn't already.
Definition: future.hh:1966
static type apply(Func &&func, FuncArgs &&... args) noexcept
Deprecated alias of invoke.
Definition: future.hh:1995
static type from_tuple(tuple_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:2004
static type from_tuple(value_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:2014
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:2018
static type from_tuple(const tuple_type &value)
Convert the tuple representation into a future.
Definition: future.hh:2008
typename type::value_type value_type
The value tuple type associated with type.
Definition: future.hh:1972
static type invoke(Func &&func, FuncArgs &&... args) noexcept
Check whether a type is a future.
Definition: future.hh:1077
Definition: future.hh:44
Definition: future.hh:446