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 <seastar/core/task.hh>
25 #include <seastar/core/thread_impl.hh>
26 #include <stdexcept>
27 #include <atomic>
28 #include <memory>
29 #include <type_traits>
30 #include <assert.h>
31 #include <cstdlib>
32 #include <seastar/core/function_traits.hh>
33 #include <seastar/util/alloc_failure_injector.hh>
34 #include <seastar/util/attribute-compat.hh>
35 #include <seastar/util/concepts.hh>
36 #include <seastar/util/noncopyable_function.hh>
37 #include <seastar/util/backtrace.hh>
38 
39 #if __cplusplus > 201703L
40 #include <concepts>
41 #endif
42 
43 namespace seastar {
44 
45 struct nested_exception : public std::exception {
46  std::exception_ptr inner;
47  std::exception_ptr outer;
48  nested_exception(std::exception_ptr inner, std::exception_ptr outer) noexcept;
50  nested_exception(const nested_exception&) noexcept;
51  [[noreturn]] void rethrow_nested() const;
52  virtual const char* what() const noexcept override;
53 };
54 
78 
135 
141 
142 
145 
146 template <class... T>
147 class promise;
148 
149 template <class... T>
150 class future;
151 
152 template <typename... T>
154 
155 struct future_state_base;
156 
163 template <typename... T, typename... A>
164 future<T...> make_ready_future(A&&... value) noexcept;
165 
172 template <typename... T>
173 future<T...> make_exception_future(std::exception_ptr&& value) noexcept;
174 
175 template <typename... T>
176 future<T...> make_exception_future(const std::exception_ptr& ex) noexcept {
177  return make_exception_future<T...>(std::exception_ptr(ex));
178 }
179 
180 template <typename... T>
181 future<T...> make_exception_future(std::exception_ptr& ex) noexcept {
182  return make_exception_future<T...>(static_cast<const std::exception_ptr&>(ex));
183 }
184 
186 void engine_exit(std::exception_ptr eptr = {});
187 
188 void report_failed_future(const std::exception_ptr& ex) noexcept;
189 
190 void report_failed_future(const future_state_base& state) noexcept;
191 
192 void with_allow_abandoned_failed_futures(unsigned count, noncopyable_function<void ()> func);
193 
195 
202 struct broken_promise : std::logic_error {
203  broken_promise();
204 };
205 
211 template <typename... T>
212 future<T...> current_exception_as_future() noexcept;
213 
214 extern template
216 
217 namespace internal {
218 template <class... T>
219 class promise_base_with_type;
220 class promise_base;
221 
222 struct monostate {};
223 
224 template <typename... T>
225 struct future_stored_type;
226 
227 template <>
228 struct future_stored_type<> {
229 #if SEASTAR_API_LEVEL < 5
230  using type = std::tuple<>;
231 #else
232  using type = monostate;
233 #endif
234 };
235 
236 template <typename T>
237 struct future_stored_type<T> {
238 #if SEASTAR_API_LEVEL < 5
239  using type = std::tuple<T>;
240 #else
241  using type = T;
242 #endif
243 };
244 
245 template <typename... T>
246 using future_stored_type_t = typename future_stored_type<T...>::type;
247 
248 template<typename T>
249 #if SEASTAR_API_LEVEL < 5
250 using future_tuple_type_t = T;
251 #else
252 using future_tuple_type_t = std::conditional_t<std::is_same_v<T, monostate>, std::tuple<>, std::tuple<T>>;
253 #endif
254 
255 // 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
256 // fails the build even if it is in the non enabled side of std::conditional.
257 template <typename T>
258 struct get0_return_type;
259 
260 template <>
261 struct get0_return_type<std::tuple<>> {
262  using type = void;
263  static type get0(std::tuple<> v) { }
264 };
265 
266 template <typename T0, typename... T>
267 struct get0_return_type<std::tuple<T0, T...>> {
268  using type = T0;
269  static type get0(std::tuple<T0, T...> v) { return std::get<0>(std::move(v)); }
270 };
271 
279 template <typename T, bool is_trivial_class>
280 struct uninitialized_wrapper_base;
281 
282 template <typename T>
283 struct uninitialized_wrapper_base<T, false> {
284  using tuple_type = future_tuple_type_t<T>;
285  union any {
286  any() noexcept {}
287  ~any() {}
288  // T can be a reference, so wrap it.
289  struct wrap {
290  T value;
291  } w;
292  } _v;
293 
294 public:
295  uninitialized_wrapper_base() noexcept = default;
296  template<typename... U>
297  std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>, void>
298  uninitialized_set(U&&... vs) {
299  new (&_v.w) typename any::wrap{T(std::forward<U>(vs)...)};
300  }
301  void uninitialized_set(tuple_type&& v) {
302  uninitialized_set(std::move(std::get<0>(v)));
303  }
304  void uninitialized_set(const tuple_type& v) {
305  uninitialized_set(std::get<0>(v));
306  }
307  T& uninitialized_get() {
308  return _v.w.value;
309  }
310  const T& uninitialized_get() const {
311  return _v.w.value;
312  }
313 };
314 
315 template <typename T> struct uninitialized_wrapper_base<T, true> : private T {
316  using tuple_type = future_tuple_type_t<T>;
317  uninitialized_wrapper_base() noexcept = default;
318  template<typename... U>
319  std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>, void>
320  uninitialized_set(U&&... vs) {
321  new (this) T(std::forward<U>(vs)...);
322  }
323  void uninitialized_set(tuple_type&& v) {
324  if constexpr (std::tuple_size_v<tuple_type> != 0) {
325  uninitialized_set(std::move(std::get<0>(v)));
326  }
327  }
328  void uninitialized_set(const tuple_type& v) {
329  if constexpr (std::tuple_size_v<tuple_type> != 0) {
330  uninitialized_set(std::get<0>(v));
331  }
332  }
333  T& uninitialized_get() {
334  return *this;
335  }
336  const T& uninitialized_get() const {
337  return *this;
338  }
339 };
340 
341 template <typename T>
342 constexpr bool can_inherit =
343 #ifdef _LIBCPP_VERSION
344 // We expect std::tuple<> to be trivially constructible and
345 // destructible. That is not the case with libc++
346 // (https://bugs.llvm.org/show_bug.cgi?id=41714). We could avoid this
347 // optimization when using libc++ and relax the asserts, but
348 // inspection suggests that std::tuple<> is trivial, it is just not
349 // marked as such.
350  std::is_same<std::tuple<>, T>::value ||
351 #endif
352  (std::is_trivially_destructible<T>::value && std::is_trivially_constructible<T>::value &&
353  std::is_class<T>::value && !std::is_final<T>::value);
354 
355 // The objective is to avoid extra space for empty types like std::tuple<>. We could use std::is_empty_v, but it is
356 // better to check that both the constructor and destructor can be skipped.
357 template <typename T>
358 struct uninitialized_wrapper
359  : public uninitialized_wrapper_base<T, can_inherit<T>> {};
360 
361 template <typename T>
362 struct is_trivially_move_constructible_and_destructible {
363  static constexpr bool value = std::is_trivially_move_constructible<T>::value && std::is_trivially_destructible<T>::value;
364 };
365 
366 template <bool... v>
367 struct all_true : std::false_type {};
368 
369 template <>
370 struct all_true<> : std::true_type {};
371 
372 template <bool... v>
373 struct all_true<true, v...> : public all_true<v...> {};
374 
375 template<typename T>
376 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper;
377 
378 template <typename... T>
379 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper<std::tuple<T...>> {
380  static constexpr bool value = all_true<is_trivially_move_constructible_and_destructible<T>::value...>::value;
381 };
382 
383 template <typename T>
384 static constexpr bool is_tuple_effectively_trivially_move_constructible_and_destructible =
385  is_tuple_effectively_trivially_move_constructible_and_destructible_helper<T>::value;
386 
387 }
388 
389 //
390 // A future/promise pair maintain one logical value (a future_state).
391 // There are up to three places that can store it, but only one is
392 // active at any time.
393 //
394 // - in the promise _local_state member variable
395 //
396 // This is necessary because a promise is created first and there
397 // would be nowhere else to put the value.
398 //
399 // - in the future _state variable
400 //
401 // This is used anytime a future exists and then has not been called
402 // yet. This guarantees a simple access to the value for any code
403 // that already has a future.
404 //
405 // - in the task associated with the .then() clause (after .then() is called,
406 // if a value was not set)
407 //
408 //
409 // The promise maintains a pointer to the state, which is modified as
410 // the state moves to a new location due to events (such as .then() or
411 // get_future being called) or due to the promise or future being
412 // moved around.
413 //
414 
415 // non templated base class to reduce code duplication
417  static_assert(sizeof(std::exception_ptr) == sizeof(void*), "exception_ptr not a pointer");
418  enum class state : uintptr_t {
419  invalid = 0,
420  future = 1,
421  // the substate is intended to decouple the run-time prevention
422  // for duplicative result extraction (calling e.g. then() twice
423  // ends up in abandoned()) from the wrapped object's destruction
424  // handling which is orchestrated by future_state. Instead of
425  // creating a temporary future_state just for the sake of setting
426  // the "invalid" in the source instance, result_unavailable can
427  // be set to ensure future_state_base::available() returns false.
428  result_unavailable = 2,
429  result = 3,
430  exception_min = 4, // or anything greater
431  };
432  union any {
433  any() noexcept { st = state::future; }
434  any(state s) noexcept { st = s; }
435  void set_exception(std::exception_ptr&& e) noexcept {
436  new (&ex) std::exception_ptr(std::move(e));
437  assert(st >= state::exception_min);
438  }
439  any(std::exception_ptr&& e) noexcept {
440  set_exception(std::move(e));
441  }
442  // From a users' perspective, a result_unavailable is not valid
443  bool valid() const noexcept { return st != state::invalid && st != state::result_unavailable; }
444  bool available() const noexcept { return st == state::result || st >= state::exception_min; }
445  bool failed() const noexcept { return __builtin_expect(st >= state::exception_min, false); }
446  void check_failure() noexcept;
447  ~any() noexcept { }
448  std::exception_ptr take_exception() noexcept {
449  std::exception_ptr ret(std::move(ex));
450  // Unfortunately in libstdc++ ~exception_ptr is defined out of line. We know that it does nothing for
451  // moved out values, so we omit calling it. This is critical for the code quality produced for this
452  // function. Without the out of line call, gcc can figure out that both sides of the if produce
453  // identical code and merges them.if
454  // We don't make any assumptions about other c++ libraries.
455  // There is request with gcc to define it inline: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90295
456 #ifndef __GLIBCXX__
457  ex.~exception_ptr();
458 #endif
459  st = state::invalid;
460  return ret;
461  }
462  void move_it(any&& x) noexcept {
463 #ifdef __GLIBCXX__
464  // Unfortunally gcc cannot fully optimize the regular
465  // implementation:
466  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95014
467  // Given what we know about the libstdc++ implementation
468  // (see the comment in take_exception), we can just
469  // memmove and zero x. We use memmove to guarantee
470  // vaild results if &x == this.
471  memmove(static_cast<void*>(this), &x, sizeof(any));
472  x.st = state::invalid;
473 #else
474  if (x.st < state::exception_min) {
475  st = x.st;
476  x.st = state::invalid;
477  } else {
478  new (&ex) std::exception_ptr(x.take_exception());
479  }
480 #endif
481  }
482  any(any&& x) noexcept {
483  move_it(std::move(x));
484  }
485  any& operator=(any&& x) noexcept {
486  check_failure();
487  // If this is a self move assignment, check_failure
488  // guarantees that we don't have an exception and calling
489  // move_it is safe.
490  move_it(std::move(x));
491  return *this;
492  }
493  bool has_result() const noexcept {
494  return st == state::result || st == state::result_unavailable;
495  }
496  state st;
497  std::exception_ptr ex;
498  } _u;
499 
500  future_state_base() noexcept = default;
501  future_state_base(state st) noexcept : _u(st) { }
502  future_state_base(std::exception_ptr&& ex) noexcept : _u(std::move(ex)) { }
503  future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
504 
505  // We never need to destruct this polymorphicly, so we can make it
506  // protected instead of virtual.
507 protected:
513  ~future_state_base() noexcept = default;
514 
515  void rethrow_exception() &&;
516  void rethrow_exception() const&;
517 
518 public:
519 
520  bool valid() const noexcept { return _u.valid(); }
521  bool available() const noexcept { return _u.available(); }
522  bool failed() const noexcept { return _u.failed(); }
523 
524  void ignore() noexcept;
525 
526  void set_exception(std::exception_ptr&& ex) noexcept {
527  assert(_u.st == state::future);
528  _u.set_exception(std::move(ex));
529  }
530  future_state_base& operator=(future_state_base&& x) noexcept = default;
531  void set_exception(future_state_base&& state) noexcept {
532  assert(_u.st == state::future);
533  *this = std::move(state);
534  }
535  std::exception_ptr get_exception() && noexcept {
536  assert(_u.st >= state::exception_min);
537  // Move ex out so future::~future() knows we've handled it
538  return _u.take_exception();
539  }
540  const std::exception_ptr& get_exception() const& noexcept {
541  assert(_u.st >= state::exception_min);
542  return _u.ex;
543  }
544  template <typename U>
545  friend struct future_state;
546  template <typename... U>
547  friend future<U...> current_exception_as_future() noexcept;
548  template <typename... U>
549  friend class future;
550  template <typename T>
551  friend struct futurize;
552 };
553 
554 void report_failed_future(future_state_base::any&& state) noexcept;
555 
556 inline void future_state_base::any::check_failure() noexcept {
557  if (failed()) {
558  report_failed_future(std::move(*this));
559  }
560 }
561 
565 
567 template <typename T>
568 struct future_state : public future_state_base, private internal::uninitialized_wrapper<T> {
569  static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible<T>::value;
570 #if SEASTAR_API_LEVEL < 5
571  static constexpr bool has_trivial_move_and_destroy = internal::is_tuple_effectively_trivially_move_constructible_and_destructible<T>;
572 #else
573  static constexpr bool has_trivial_move_and_destroy = internal::is_trivially_move_constructible_and_destructible<T>::value;
574 #endif
575  static_assert(std::is_nothrow_move_constructible<T>::value,
576  "Types must be no-throw move constructible");
577  static_assert(std::is_nothrow_destructible<T>::value,
578  "Types must be no-throw destructible");
579  future_state() noexcept = default;
580  void move_it(future_state&& x) noexcept {
581  if constexpr (has_trivial_move_and_destroy) {
582  memmove(reinterpret_cast<char*>(&this->uninitialized_get()),
583  &x.uninitialized_get(),
584  internal::used_size<T>::value);
585  } else if (_u.has_result()) {
586  this->uninitialized_set(std::move(x.uninitialized_get()));
587  std::destroy_at(&x.uninitialized_get());
588  }
589  }
590 
591  [[gnu::always_inline]]
592  future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
593  move_it(std::move(x));
594  }
595 
596  void clear() noexcept {
597  if (_u.has_result()) {
598  std::destroy_at(&this->uninitialized_get());
599  } else {
600  _u.check_failure();
601  }
602  }
603  __attribute__((always_inline))
604  ~future_state() noexcept {
605  clear();
606  }
607  future_state& operator=(future_state&& x) noexcept {
608  clear();
609  future_state_base::operator=(std::move(x));
610  // If &x == this, _u.st is now state::invalid and so it is
611  // safe to call move_it.
612  move_it(std::move(x));
613  return *this;
614  }
615  template <typename... A>
616  future_state(ready_future_marker, A&&... a) noexcept : future_state_base(state::result) {
617  try {
618  this->uninitialized_set(std::forward<A>(a)...);
619  } catch (...) {
620  new (this) future_state(current_exception_future_marker());
621  }
622  }
623  template <typename... A>
624  void set(A&&... a) noexcept {
625  assert(_u.st == state::future);
626  new (this) future_state(ready_future_marker(), std::forward<A>(a)...);
627  }
628  future_state(exception_future_marker m, std::exception_ptr&& ex) noexcept : future_state_base(std::move(ex)) { }
629  future_state(exception_future_marker m, future_state_base&& state) noexcept : future_state_base(std::move(state)) { }
630  future_state(current_exception_future_marker m) noexcept : future_state_base(m) { }
631  future_state(nested_exception_marker m, future_state_base&& old) noexcept : future_state_base(m, std::move(old)) { }
632  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)) { }
633  T&& get_value() && noexcept {
634  assert(_u.st == state::result);
635  return static_cast<T&&>(this->uninitialized_get());
636  }
637  T&& take_value() && noexcept {
638  assert(_u.st == state::result);
639  _u.st = state::result_unavailable;
640  return static_cast<T&&>(this->uninitialized_get());
641  }
642  template<typename U = T>
643  const std::enable_if_t<std::is_copy_constructible<U>::value, U>& get_value() const& noexcept(copy_noexcept) {
644  assert(_u.st == state::result);
645  return this->uninitialized_get();
646  }
647  T&& take() && {
648  assert(available());
649  if (_u.st >= state::exception_min) {
650  std::move(*this).rethrow_exception();
651  }
652  _u.st = state::result_unavailable;
653  return static_cast<T&&>(this->uninitialized_get());
654  }
655  T&& get() && {
656  assert(available());
657  if (_u.st >= state::exception_min) {
658  std::move(*this).rethrow_exception();
659  }
660  return static_cast<T&&>(this->uninitialized_get());
661  }
662  const T& get() const& {
663  assert(available());
664  if (_u.st >= state::exception_min) {
665  rethrow_exception();
666  }
667  return this->uninitialized_get();
668  }
669  using get0_return_type = typename internal::get0_return_type<internal::future_tuple_type_t<T>>::type;
670  static get0_return_type get0(T&& x) {
671  return internal::get0_return_type<T>::get0(std::move(x));
672  }
673 
674  get0_return_type get0() {
675 #if SEASTAR_API_LEVEL < 5
676  return get0(std::move(*this).get());
677 #else
678  return std::move(*this).get();
679 #endif
680  }
681 };
682 
683 template <typename... T>
684 class continuation_base : public task {
685 protected:
686  using future_state = seastar::future_state<internal::future_stored_type_t<T...>>;
687  future_state _state;
688  using future_type = future<T...>;
689  using promise_type = promise<T...>;
690 public:
691  continuation_base() noexcept = default;
692  void set_state(future_state&& state) noexcept {
693  _state = std::move(state);
694  }
695  // This override of waiting_task() is needed here because there are cases
696  // when backtrace is obtained from the destructor of this class and objects
697  // of derived classes are already destroyed at that time. If we didn't
698  // have this override we would get a "pure virtual function call" exception.
699  virtual task* waiting_task() noexcept override { return nullptr; }
700  friend class internal::promise_base_with_type<T...>;
701  friend class promise<T...>;
702  friend class future<T...>;
703 };
704 
705 // Given a future type, find the corresponding continuation_base.
706 template <typename Future>
707 struct continuation_base_from_future;
708 
709 template <typename... T>
710 struct continuation_base_from_future<future<T...>> {
711  using type = continuation_base<T...>;
712 };
713 
714 template <typename Future>
715 using continuation_base_from_future_t = typename continuation_base_from_future<Future>::type;
716 
717 template <typename Promise, typename... T>
718 class continuation_base_with_promise : public continuation_base<T...> {
719  friend class internal::promise_base_with_type<T...>;
720 protected:
721  continuation_base_with_promise(Promise&& pr) noexcept : _pr(std::move(pr)) {
722  task::make_backtrace();
723  }
724  virtual task* waiting_task() noexcept override;
725  Promise _pr;
726 };
727 
728 template <typename Promise, typename Func, typename Wrapper, typename... T>
729 struct continuation final : continuation_base_with_promise<Promise, T...> {
730  // Func is the original function passed to then/then_wrapped. The
731  // Wrapper is a helper function that implements the specific logic
732  // needed by then/then_wrapped. We call the wrapper passing it the
733  // original function, promise and state.
734  // Note that if Func's move constructor throws, this will call
735  // std::unexpected. We could try to require Func to be nothrow
736  // move constructible, but that will cause a lot of churn. Since
737  // we can't support a failure to create a continuation, calling
738  // std::unexpected as close to the failure as possible is the best
739  // we can do.
740  continuation(Promise&& pr, Func&& func, Wrapper&& wrapper) noexcept
741  : continuation_base_with_promise<Promise, T...>(std::move(pr))
742  , _func(std::move(func))
743  , _wrapper(std::move(wrapper)) {}
744  virtual void run_and_dispose() noexcept override {
745  try {
746  _wrapper(std::move(this->_pr), _func, std::move(this->_state));
747  } catch (...) {
748  this->_pr.set_to_current_exception();
749  }
750  delete this;
751  }
752  Func _func;
753  [[no_unique_address]] Wrapper _wrapper;
754 };
755 
756 #if SEASTAR_API_LEVEL < 4
757 
758 // This is an internal future<> payload for seastar::when_all_succeed(). It is used
759 // to return a variadic future (when two or more of its input futures were non-void),
760 // but with variadic futures deprecated and soon gone this is no longer possible.
761 //
762 // Instead, we use this tuple type, and future::then() knows to unpack it.
763 //
764 // The whole thing is temporary for a transition period.
765 template <typename... T>
766 struct when_all_succeed_tuple : std::tuple<T...> {
767  using std::tuple<T...>::tuple;
768  when_all_succeed_tuple(std::tuple<T...>&& t)
769  noexcept(std::is_nothrow_move_constructible<std::tuple<T...>>::value)
770  : std::tuple<T...>(std::move(t)) {}
771 };
772 
773 #endif
774 
775 namespace internal {
776 
777 template <typename... T>
778 future<T...> make_exception_future(future_state_base&& state) noexcept;
779 
780 template <typename... T, typename U>
781 void set_callback(future<T...>& fut, U* callback) noexcept;
782 
783 class future_base;
784 
785 class promise_base {
786 protected:
787  enum class urgent { no, yes };
788  future_base* _future = nullptr;
789 
790  // This points to the future_state that is currently being
791  // used. See comment above the future_state struct definition for
792  // details.
793  future_state_base* _state;
794 
795  task* _task = nullptr;
796 
797  promise_base(const promise_base&) = delete;
798  promise_base(future_state_base* state) noexcept : _state(state) {}
799  promise_base(future_base* future, future_state_base* state) noexcept;
800  void move_it(promise_base&& x) noexcept;
801  promise_base(promise_base&& x) noexcept;
802 
803  void clear() noexcept;
804 
805  // We never need to destruct this polymorphicly, so we can make it
806  // protected instead of virtual
807  ~promise_base() noexcept {
808  clear();
809  }
810 
811  void operator=(const promise_base&) = delete;
812  promise_base& operator=(promise_base&& x) noexcept;
813 
814  template<urgent Urgent>
815  void make_ready() noexcept;
816 
817  template<typename T>
818  void set_exception_impl(T&& val) noexcept {
819  if (_state) {
820  _state->set_exception(std::move(val));
821  make_ready<urgent::no>();
822  } else {
823  // We get here if promise::get_future is called and the
824  // returned future is destroyed without creating a
825  // continuation.
826  // In older versions of seastar we would store a local
827  // copy of ex and warn in the promise destructor.
828  // Since there isn't any way for the user to clear
829  // the exception, we issue the warning from here.
830  report_failed_future(val);
831  }
832  }
833 
834  void set_exception(future_state_base&& state) noexcept {
835  set_exception_impl(std::move(state));
836  }
837 
838  void set_exception(std::exception_ptr&& ex) noexcept {
839  set_exception_impl(std::move(ex));
840  }
841 
842  void set_exception(const std::exception_ptr& ex) noexcept {
843  set_exception(std::exception_ptr(ex));
844  }
845 
846  template<typename Exception>
847  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
848  set_exception(make_exception_ptr(std::forward<Exception>(e)));
849  }
850 
851  friend class future_base;
852  template <typename... U> friend class seastar::future;
853 
854 public:
859  void set_to_current_exception() noexcept;
860 
862  task* waiting_task() const noexcept { return _task; }
863 };
864 
871 template <typename... T>
872 class promise_base_with_type : protected internal::promise_base {
873 protected:
874  using future_state = seastar::future_state<future_stored_type_t<T...>>;
875  future_state* get_state() noexcept {
876  return static_cast<future_state*>(_state);
877  }
878  static constexpr bool copy_noexcept = future_state::copy_noexcept;
879 public:
880  promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
881  promise_base_with_type(future<T...>* future) noexcept : promise_base(future, &future->_state) { }
882  promise_base_with_type(promise_base_with_type&& x) noexcept = default;
883  promise_base_with_type(const promise_base_with_type&) = delete;
884  promise_base_with_type& operator=(promise_base_with_type&& x) noexcept = default;
885  void operator=(const promise_base_with_type&) = delete;
886 
887  void set_urgent_state(future_state&& state) noexcept {
888  auto* ptr = get_state();
889  // The state can be null if the corresponding future has been
890  // destroyed without producing a continuation.
891  if (ptr) {
892  // FIXME: This is a fairly expensive assert. It would be a
893  // good candidate for being disabled in release builds if
894  // we had such an assert.
895  assert(ptr->_u.st == future_state_base::state::future);
896  new (ptr) future_state(std::move(state));
897  make_ready<urgent::yes>();
898  }
899  }
900 
901  template <typename... A>
902  void set_value(A&&... a) noexcept {
903  if (auto *s = get_state()) {
904  s->set(std::forward<A>(a)...);
905  make_ready<urgent::no>();
906  }
907  }
908 
913  void set_to_current_exception() noexcept {
914  internal::promise_base::set_to_current_exception();
915  }
916 
918  using internal::promise_base::waiting_task;
919 
920 private:
921 
922  template <typename... U>
923  friend class seastar::future;
924 
925  friend future_state;
926 };
927 }
929 
935 template <typename... T>
936 class promise : private internal::promise_base_with_type<T...> {
937  using future_state = typename internal::promise_base_with_type<T...>::future_state;
938  future_state _local_state;
939 
940 public:
944  promise() noexcept : internal::promise_base_with_type<T...>(&_local_state) {}
945 
947  void move_it(promise&& x) noexcept;
948  promise(promise&& x) noexcept : internal::promise_base_with_type<T...>(std::move(x)) {
949  move_it(std::move(x));
950  }
951  promise(const promise&) = delete;
952  promise& operator=(promise&& x) noexcept {
953  internal::promise_base_with_type<T...>::operator=(std::move(x));
954  // If this is a self-move, _state is now nullptr and it is
955  // safe to call move_it.
956  move_it(std::move(x));
957  return *this;
958  }
959  void operator=(const promise&) = delete;
960 
965  void set_to_current_exception() noexcept {
966  internal::promise_base::set_to_current_exception();
967  }
968 
970  using internal::promise_base::waiting_task;
971 
978  future<T...> get_future() noexcept;
979 
991  template <typename... A>
992  void set_value(A&&... a) noexcept {
993  internal::promise_base_with_type<T...>::set_value(std::forward<A>(a)...);
994  }
995 
1000  void set_exception(std::exception_ptr&& ex) noexcept {
1001  internal::promise_base::set_exception(std::move(ex));
1002  }
1003 
1004  void set_exception(const std::exception_ptr& ex) noexcept {
1005  internal::promise_base::set_exception(ex);
1006  }
1007 
1012  template<typename Exception>
1013  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
1014  internal::promise_base::set_exception(std::forward<Exception>(e));
1015  }
1016 
1017  using internal::promise_base_with_type<T...>::set_urgent_state;
1018 
1019  template <typename... U>
1020  friend class future;
1021 };
1022 
1028 template<>
1029 class promise<void> : public promise<> {};
1030 
1032 
1035 
1036 
1042 template <typename... T> struct is_future : std::false_type {};
1043 
1046 template <typename... T> struct is_future<future<T...>> : std::true_type {};
1047 
1049 
1050 
1054 template <typename T>
1055 struct futurize;
1056 
1057 SEASTAR_CONCEPT(
1058 
1059 template <typename T>
1060 concept Future = is_future<T>::value;
1061 
1062 template <typename Func, typename... T>
1063 concept CanInvoke = std::invocable<Func, T...>;
1064 
1065 // Deprecated alias
1066 template <typename Func, typename... T>
1067 concept CanApply = CanInvoke<Func, T...>;
1068 
1069 template <typename Func, typename... T>
1070 concept CanApplyTuple
1071  = sizeof...(T) == 1
1072  && requires (Func func, std::tuple<T...> wrapped_val) {
1073  { std::apply(func, std::get<0>(std::move(wrapped_val))) };
1074  };
1075 
1076 template <typename Func, typename Return, typename... T>
1077 concept InvokeReturns = requires (Func f, T... args) {
1078  { f(std::forward<T>(args)...) } -> std::same_as<Return>;
1079 };
1080 
1081 // Deprecated alias
1082 template <typename Func, typename Return, typename... T>
1083 concept ApplyReturns = InvokeReturns<Func, Return, T...>;
1084 
1085 template <typename Func, typename... T>
1086 concept InvokeReturnsAnyFuture = requires (Func f, T... args) {
1087  requires is_future<decltype(f(std::forward<T>(args)...))>::value;
1088 };
1089 
1090 // Deprecated alias
1091 template <typename Func, typename... T>
1092 concept ApplyReturnsAnyFuture = InvokeReturnsAnyFuture<Func, T...>;
1093 
1094 )
1095 
1097 
1098 // Converts a type to a future type, if it isn't already.
1099 template <typename T>
1100 using futurize_t = typename futurize<T>::type;
1101 
1103 
1104 template<typename Func, typename... Args>
1105 auto futurize_invoke(Func&& func, Args&&... args) noexcept;
1106 
1107 template<typename Func, typename... Args>
1108 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept;
1109 
1112 namespace internal {
1113 class future_base {
1114 protected:
1115  promise_base* _promise;
1116  future_base() noexcept : _promise(nullptr) {}
1117  future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
1118  _promise->_future = this;
1119  _promise->_state = state;
1120  }
1121 
1122  void move_it(future_base&& x, future_state_base* state) noexcept {
1123  _promise = x._promise;
1124  if (auto* p = _promise) {
1125  x.detach_promise();
1126  p->_future = this;
1127  p->_state = state;
1128  }
1129  }
1130 
1131  future_base(future_base&& x, future_state_base* state) noexcept {
1132  move_it(std::move(x), state);
1133  }
1134 
1135  void clear() noexcept {
1136  if (_promise) {
1137  detach_promise();
1138  }
1139  }
1140 
1141  ~future_base() noexcept {
1142  clear();
1143  }
1144 
1145  promise_base* detach_promise() noexcept {
1146  _promise->_state = nullptr;
1147  _promise->_future = nullptr;
1148  return std::exchange(_promise, nullptr);
1149  }
1150 
1151  void schedule(task* tws, future_state_base* state) noexcept {
1152  promise_base* p = detach_promise();
1153  p->_state = state;
1154  p->_task = tws;
1155  }
1156 
1157  void do_wait() noexcept;
1158 
1159 #ifdef SEASTAR_COROUTINES_ENABLED
1160  void set_coroutine(task& coroutine) noexcept;
1161 #endif
1162 
1163  friend class promise_base;
1164 };
1165 
1166 
1167 // This is a customization point for future::then()'s implementation.
1168 // It behaves differently when the future value type is a when_all_succeed_tuple
1169 // instantiation, indicating we need to unpack the tuple into multiple lambda
1170 // arguments.
1171 template <typename Future>
1172 struct call_then_impl;
1173 
1174 // Generic case - the input is not a future<when_all_succeed_tuple<...>>, so
1175 // we just forward everything to future::then_impl.
1176 template <typename... T>
1177 struct call_then_impl<future<T...>> {
1178  template <typename Func>
1179  using result_type = futurize_t<std::invoke_result_t<Func, T&&...>>;
1180 
1181  template <typename Func>
1182  using func_type = result_type<Func> (T&&...);
1183 
1184  template <typename Func>
1185  static auto run(future<T...>& fut, Func&& func) noexcept {
1186  return fut.then_impl(std::forward<Func>(func));
1187  }
1188 };
1189 
1190 #if SEASTAR_API_LEVEL < 4
1191 
1192 // Special case: we unpack the tuple before calling the function
1193 template <typename... T>
1194 struct call_then_impl<future<when_all_succeed_tuple<T...>>> {
1195  template <typename Func>
1196  using result_type = futurize_t<std::invoke_result_t<Func, T&&...>>;
1197 
1198  template <typename Func>
1199  using func_type = result_type<Func> (T&&...);
1200 
1201  using was_tuple = when_all_succeed_tuple<T...>;
1202  using std_tuple = std::tuple<T...>;
1203 
1204  template <typename Func>
1205  static auto run(future<was_tuple>& fut, Func&& func) noexcept {
1206  // constructing func in the lambda can throw, but there's nothing we can do
1207  // about it, similar to #84.
1208  return fut.then_impl([func = std::forward<Func>(func)] (was_tuple&& t) mutable {
1209  return std::apply(func, static_cast<std_tuple&&>(std::move(t)));
1210  });
1211  }
1212 };
1213 
1214 #endif
1215 
1216 template <typename Func, typename... Args>
1217 using call_then_impl_result_type = typename call_then_impl<future<Args...>>::template result_type<Func>;
1218 
1219 SEASTAR_CONCEPT(
1220 template <typename Func, typename... Args>
1221 concept CanInvokeWhenAllSucceed = requires {
1222  typename call_then_impl_result_type<Func, Args...>;
1223 };
1224 )
1225 
1226 template <typename Func>
1227 struct result_of_apply {
1228  // no "type" member if not a function call signature or not a tuple
1229 };
1230 
1231 template <typename Func, typename... T>
1232 struct result_of_apply<Func (std::tuple<T...>)> : std::result_of<Func (T...)> {
1233  // Let std::result_of determine the result if the input is a tuple
1234 };
1235 
1236 template <typename Func>
1237 using result_of_apply_t = typename result_of_apply<Func>::type;
1238 
1239 }
1240 
1241 template <typename Promise, typename... T>
1242 task* continuation_base_with_promise<Promise, T...>::waiting_task() noexcept {
1243  return _pr.waiting_task();
1244 }
1245 
1288 template <typename... T>
1289 class SEASTAR_NODISCARD future : private internal::future_base {
1290  using future_state = seastar::future_state<internal::future_stored_type_t<T...>>;
1291  future_state _state;
1292  static constexpr bool copy_noexcept = future_state::copy_noexcept;
1293  using call_then_impl = internal::call_then_impl<future>;
1294 
1295  static_assert(sizeof...(T) <= 1, "variadic futures are not supported");
1296 private:
1297  // This constructor creates a future that is not ready but has no
1298  // associated promise yet. The use case is to have a less flexible
1299  // but more efficient future/promise pair where we know that
1300  // promise::set_value cannot possibly be called without a matching
1301  // future and so that promise doesn't need to store a
1302  // future_state.
1303  future(future_for_get_promise_marker m) noexcept { }
1304 
1305  future(promise<T...>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
1306  template <typename... A>
1307  future(ready_future_marker m, A&&... a) noexcept : _state(m, std::forward<A>(a)...) { }
1308  future(future_state_base::current_exception_future_marker m) noexcept : _state(m) {}
1309  future(future_state_base::nested_exception_marker m, future_state_base&& old) noexcept : _state(m, std::move(old)) {}
1310  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)) {}
1311  future(exception_future_marker m, std::exception_ptr&& ex) noexcept : _state(m, std::move(ex)) { }
1312  future(exception_future_marker m, future_state_base&& state) noexcept : _state(m, std::move(state)) { }
1313  [[gnu::always_inline]]
1314  explicit future(future_state&& state) noexcept
1315  : _state(std::move(state)) {
1316  }
1317  internal::promise_base_with_type<T...> get_promise() noexcept {
1318  assert(!_promise);
1319  return internal::promise_base_with_type<T...>(this);
1320  }
1321  internal::promise_base_with_type<T...>* detach_promise() noexcept {
1322  return static_cast<internal::promise_base_with_type<T...>*>(future_base::detach_promise());
1323  }
1324  void schedule(continuation_base<T...>* tws) noexcept {
1325  future_base::schedule(tws, &tws->_state);
1326  }
1327  template <typename Pr, typename Func, typename Wrapper>
1328  void schedule(Pr&& pr, Func&& func, Wrapper&& wrapper) noexcept {
1329  // If this new throws a std::bad_alloc there is nothing that
1330  // can be done about it. The corresponding future is not ready
1331  // and we cannot break the chain. Since this function is
1332  // noexcept, it will call std::terminate if new throws.
1333  memory::disable_failure_guard dfg;
1334  auto tws = new continuation<Pr, Func, Wrapper, T...>(std::move(pr), std::move(func), std::move(wrapper));
1335  // In a debug build we schedule ready futures, but not in
1336  // other build modes.
1337 #ifdef SEASTAR_DEBUG
1338  if (_state.available()) {
1339  tws->set_state(std::move(_state));
1340  ::seastar::schedule(tws);
1341  return;
1342  }
1343 #endif
1344  schedule(tws);
1345  _state._u.st = future_state_base::state::invalid;
1346  }
1347 
1348  [[gnu::always_inline]]
1349  future_state&& get_available_state_ref() noexcept {
1350  if (_promise) {
1351  detach_promise();
1352  }
1353  return std::move(_state);
1354  }
1355 
1356  future<T...> rethrow_with_nested(future_state_base&& n) noexcept {
1357  return future<T...>(future_state_base::nested_exception_marker(), std::move(n), std::move(_state));
1358  }
1359 
1360  future<T...> rethrow_with_nested() noexcept {
1361  return future<T...>(future_state_base::nested_exception_marker(), std::move(_state));
1362  }
1363 
1364  template<typename... U>
1365  friend class shared_future;
1366 public:
1368  using value_type = internal::future_stored_type_t<T...>;
1369  using tuple_type = internal::future_tuple_type_t<value_type>;
1371  using promise_type = promise<T...>;
1373  [[gnu::always_inline]]
1374  future(future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1375  future(const future&) = delete;
1376  future& operator=(future&& x) noexcept {
1377  clear();
1378  move_it(std::move(x), &_state);
1379  _state = std::move(x._state);
1380  return *this;
1381  }
1382  void operator=(const future&) = delete;
1392  [[gnu::always_inline]]
1394  wait();
1395  return get_available_state_ref().take();
1396  }
1397 
1398  [[gnu::always_inline]]
1399  std::exception_ptr get_exception() noexcept {
1400  return get_available_state_ref().get_exception();
1401  }
1402 
1411  using get0_return_type = typename future_state::get0_return_type;
1412  get0_return_type get0() {
1413 #if SEASTAR_API_LEVEL < 5
1414  return future_state::get0(get());
1415 #else
1416  return (get0_return_type)get();
1417 #endif
1418  }
1419 
1425  void wait() noexcept {
1426  if (_state.available()) {
1427  return;
1428  }
1429  do_wait();
1430  }
1431 
1435  [[gnu::always_inline]]
1436  bool available() const noexcept {
1437  return _state.available();
1438  }
1439 
1443  [[gnu::always_inline]]
1444  bool failed() const noexcept {
1445  return _state.failed();
1446  }
1447 
1463  template <typename Func, typename Result = futurize_t<typename call_then_impl::template result_type<Func>>>
1464  SEASTAR_CONCEPT( requires std::invocable<Func, T...> || internal::CanInvokeWhenAllSucceed<Func, T...>)
1465  Result
1466  then(Func&& func) noexcept {
1467  // The implementation of then() is customized via the call_then_impl helper
1468  // template, in order to special case the results of when_all_succeed().
1469  // when_all_succeed() used to return a variadic future, which is deprecated, so
1470  // now it returns a when_all_succeed_tuple, which we intercept in call_then_impl,
1471  // and treat it as a variadic future.
1472 #ifndef SEASTAR_TYPE_ERASE_MORE
1473  return call_then_impl::run(*this, std::move(func));
1474 #else
1475  using func_type = typename call_then_impl::template func_type<Func>;
1477  {
1479  ncf = noncopyable_function<func_type>([func = std::forward<Func>(func)](auto&&... args) mutable {
1480  return futurize_invoke(func, std::forward<decltype(args)>(args)...);
1481  });
1482  }
1483  return call_then_impl::run(*this, std::move(ncf));
1484 #endif
1485  }
1486 
1506  template <typename Func, typename Result = futurize_t<internal::result_of_apply_t<Func (T...)>>>
1507  SEASTAR_CONCEPT( requires (sizeof...(T) == 1) && ::seastar::CanApplyTuple<Func, T...>)
1508  Result
1509  then_unpack(Func&& func) noexcept {
1510  return then([func = std::forward<Func>(func)] (T&&... tuple) mutable {
1511  // sizeof...(tuple) is required to be 1
1512  return std::apply(func, std::move(tuple)...);
1513  });
1514  }
1515 
1516 private:
1517 
1518  // Keep this simple so that Named Return Value Optimization is used.
1519  template <typename Func, typename Result>
1520  Result then_impl_nrvo(Func&& func) noexcept {
1521  using futurator = futurize<std::invoke_result_t<Func, T&&...>>;
1522  typename futurator::type fut(future_for_get_promise_marker{});
1523  using pr_type = decltype(fut.get_promise());
1524  schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1525  if (state.failed()) {
1526  pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1527  } else {
1528  futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1529 #if SEASTAR_API_LEVEL < 5
1530  return std::apply(func, std::move(state).get_value());
1531 #else
1532  // clang thinks that "state" is not used, below, for future<>.
1533  // Make it think it is used to avoid an unused-lambda-capture warning.
1534  (void)state;
1535  return std::invoke(func, static_cast<T&&>(std::move(state).get_value())...);
1536 #endif
1537  });
1538  }
1539  });
1540  return fut;
1541  }
1542 
1543  template <typename Func, typename Result = futurize_t<std::invoke_result_t<Func, T&&...>>>
1544  Result
1545  then_impl(Func&& func) noexcept {
1546 #ifndef SEASTAR_DEBUG
1547  using futurator = futurize<std::invoke_result_t<Func, T&&...>>;
1548  if (failed()) {
1549  return futurator::make_exception_future(static_cast<future_state_base&&>(get_available_state_ref()));
1550  } else if (available()) {
1551 #if SEASTAR_API_LEVEL < 5
1552  return futurator::apply(std::forward<Func>(func), get_available_state_ref().take_value());
1553 #else
1554  return futurator::invoke(std::forward<Func>(func), get_available_state_ref().take_value());
1555 #endif
1556  }
1557 #endif
1558  return then_impl_nrvo<Func, Result>(std::forward<Func>(func));
1559  }
1560 
1561 public:
1577  template <typename Func, typename FuncResult = std::invoke_result_t<Func, future>>
1578  SEASTAR_CONCEPT( requires std::invocable<Func, future> )
1579  futurize_t<FuncResult>
1580  then_wrapped(Func&& func) & noexcept {
1581  return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1582  }
1583 
1584  template <typename Func, typename FuncResult = std::invoke_result_t<Func, future&&>>
1585  SEASTAR_CONCEPT( requires std::invocable<Func, future&&> )
1586  futurize_t<FuncResult>
1587  then_wrapped(Func&& func) && noexcept {
1588  return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1589  }
1590 
1591 private:
1592 
1593  template <bool AsSelf, typename FuncResult, typename Func>
1594  futurize_t<FuncResult>
1595  then_wrapped_maybe_erase(Func&& func) noexcept {
1596 #ifndef SEASTAR_TYPE_ERASE_MORE
1597  return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1598 #else
1599  using futurator = futurize<FuncResult>;
1600  using WrapFuncResult = typename futurator::type;
1601  noncopyable_function<WrapFuncResult (future&&)> ncf;
1602  {
1603  memory::disable_failure_guard dfg;
1604  ncf = noncopyable_function<WrapFuncResult(future &&)>([func = std::forward<Func>(func)](future&& f) mutable {
1605  return futurator::invoke(func, std::move(f));
1606  });
1607  }
1608  return then_wrapped_common<AsSelf, WrapFuncResult>(std::move(ncf));
1609 #endif
1610  }
1611 
1612  // Keep this simple so that Named Return Value Optimization is used.
1613  template <typename FuncResult, typename Func>
1614  futurize_t<FuncResult>
1615  then_wrapped_nrvo(Func&& func) noexcept {
1616  using futurator = futurize<FuncResult>;
1617  typename futurator::type fut(future_for_get_promise_marker{});
1618  using pr_type = decltype(fut.get_promise());
1619  schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1620  futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1621  return func(future(std::move(state)));
1622  });
1623  });
1624  return fut;
1625  }
1626 
1627 
1628  template <bool AsSelf, typename FuncResult, typename Func>
1629  futurize_t<FuncResult>
1630  then_wrapped_common(Func&& func) noexcept {
1631 #ifndef SEASTAR_DEBUG
1632  using futurator = futurize<FuncResult>;
1633  if (available()) {
1634  if constexpr (AsSelf) {
1635  if (_promise) {
1636  detach_promise();
1637  }
1638  return futurator::invoke(std::forward<Func>(func), std::move(*this));
1639  } else {
1640  return futurator::invoke(std::forward<Func>(func), future(get_available_state_ref()));
1641  }
1642  }
1643 #endif
1644  return then_wrapped_nrvo<FuncResult, Func>(std::forward<Func>(func));
1645  }
1646 
1647  void forward_to(internal::promise_base_with_type<T...>&& pr) noexcept {
1648  if (_state.available()) {
1649  pr.set_urgent_state(std::move(_state));
1650  } else {
1651  *detach_promise() = std::move(pr);
1652  }
1653  }
1654 
1655 public:
1666  void forward_to(promise<T...>&& pr) noexcept {
1667  if (_state.available()) {
1668  pr.set_urgent_state(std::move(_state));
1669  } else if (&pr._local_state != pr._state) {
1670  // The only case when _state points to _local_state is
1671  // when get_future was never called. Given that pr will
1672  // soon be destroyed, we know get_future will never be
1673  // called and we can just ignore this request.
1674  *detach_promise() = std::move(pr);
1675  }
1676  }
1677 
1678 
1679 
1695  template <typename Func>
1696  SEASTAR_CONCEPT( requires std::invocable<Func> )
1697  future<T...> finally(Func&& func) noexcept {
1698  return then_wrapped(finally_body<Func, is_future<std::invoke_result_t<Func>>::value>(std::forward<Func>(func)));
1699  }
1700 
1701 
1702  template <typename Func, bool FuncReturnsFuture>
1704 
1705  template <typename Func>
1706  struct finally_body<Func, true> {
1707  Func _func;
1708 
1709  finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1710  { }
1711 
1712  future<T...> operator()(future<T...>&& result) noexcept {
1713  return futurize_invoke(_func).then_wrapped([result = std::move(result)](auto&& f_res) mutable {
1714  if (!f_res.failed()) {
1715  return std::move(result);
1716  } else {
1717  return result.rethrow_with_nested(std::move(f_res._state));
1718  }
1719  });
1720  }
1721  };
1722 
1723  template <typename Func>
1724  struct finally_body<Func, false> {
1725  Func _func;
1726 
1727  finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1728  { }
1729 
1730  future<T...> operator()(future<T...>&& result) noexcept {
1731  try {
1732  _func();
1733  return std::move(result);
1734  } catch (...) {
1735  return result.rethrow_with_nested();
1736  }
1737  };
1738  };
1739 
1744  future<> or_terminate() noexcept {
1745  return then_wrapped([] (auto&& f) {
1746  try {
1747  f.get();
1748  } catch (...) {
1749  engine_exit(std::current_exception());
1750  }
1751  });
1752  }
1753 
1759  // We need the generic variadic lambda, below, because then() behaves differently
1760  // when value_type is when_all_succeed_tuple
1761  return then([] (auto&&...) {});
1762  }
1763 
1777  template <typename Func>
1778  /* Broken?
1779  SEASTAR_CONCEPT( requires ::seastar::InvokeReturns<Func, future<T...>, std::exception_ptr>
1780  || (sizeof...(T) == 0 && ::seastar::InvokeReturns<Func, void, std::exception_ptr>)
1781  || (sizeof...(T) == 1 && ::seastar::InvokeReturns<Func, T..., std::exception_ptr>)
1782  ) */
1783  future<T...> handle_exception(Func&& func) noexcept {
1784  return then_wrapped([func = std::forward<Func>(func)]
1785  (auto&& fut) mutable -> future<T...> {
1786  if (!fut.failed()) {
1787  return make_ready_future<T...>(fut.get());
1788  } else {
1789  return futurize_invoke(func, fut.get_exception());
1790  }
1791  });
1792  }
1793 
1804  template <typename Func>
1805  future<T...> handle_exception_type(Func&& func) noexcept {
1806  using trait = function_traits<Func>;
1807  static_assert(trait::arity == 1, "func can take only one parameter");
1808  using ex_type = typename trait::template arg<0>::type;
1809  return then_wrapped([func = std::forward<Func>(func)]
1810  (auto&& fut) mutable -> future<T...> {
1811  try {
1812  return make_ready_future<T...>(fut.get());
1813  } catch(ex_type& ex) {
1814  return futurize_invoke(func, ex);
1815  }
1816  });
1817  }
1818 
1824  void ignore_ready_future() noexcept {
1825  _state.ignore();
1826  }
1827 
1828 #ifdef SEASTAR_COROUTINES_ENABLED
1829  using future_base::set_coroutine;
1830 #endif
1831 private:
1832  void set_callback(continuation_base<T...>* callback) noexcept {
1833  if (_state.available()) {
1834  callback->set_state(get_available_state_ref());
1835  ::seastar::schedule(callback);
1836  } else {
1837  assert(_promise);
1838  schedule(callback);
1839  }
1840 
1841  }
1842 
1844  template <typename... U>
1845  friend class future;
1846  template <typename... U>
1847  friend class promise;
1848  template <typename U>
1849  friend struct futurize;
1850  template <typename... U>
1851  friend class internal::promise_base_with_type;
1852  template <typename... U, typename... A>
1853  friend future<U...> make_ready_future(A&&... value) noexcept;
1854  template <typename... U>
1855  friend future<U...> make_exception_future(std::exception_ptr&& ex) noexcept;
1856  template <typename... U, typename Exception>
1857  friend future<U...> make_exception_future(Exception&& ex) noexcept;
1858  template <typename... U>
1859  friend future<U...> internal::make_exception_future(future_state_base&& state) noexcept;
1860  template <typename... U>
1861  friend future<U...> current_exception_as_future() noexcept;
1862  template <typename... U, typename V>
1863  friend void internal::set_callback(future<U...>&, V*) noexcept;
1864  template <typename Future>
1865  friend struct internal::call_then_impl;
1867 };
1868 
1869 
1870 namespace internal {
1871 template <typename T>
1872 struct futurize_base {
1874  using type = future<T>;
1876  using promise_type = promise<T>;
1877  using promise_base_with_type = internal::promise_base_with_type<T>;
1878 
1880  static inline type convert(T&& value) { return make_ready_future<T>(std::move(value)); }
1881  static inline type convert(type&& value) { return std::move(value); }
1882 
1884  template <typename Arg>
1885  static inline type make_exception_future(Arg&& arg) noexcept;
1886 };
1887 
1888 template <>
1889 struct futurize_base<void> {
1890  using type = future<>;
1891  using promise_type = promise<>;
1892  using promise_base_with_type = internal::promise_base_with_type<>;
1893 
1894  static inline type convert(type&& value) {
1895  return std::move(value);
1896  }
1897  template <typename Arg>
1898  static inline type make_exception_future(Arg&& arg) noexcept;
1899 };
1900 
1901 template <typename T>
1902 struct futurize_base<future<T>> : public futurize_base<T> {};
1903 
1904 template <>
1905 struct futurize_base<future<>> : public futurize_base<void> {};
1906 }
1907 
1908 template <typename T>
1909 struct futurize : public internal::futurize_base<T> {
1910  using base = internal::futurize_base<T>;
1911  using type = typename base::type;
1912  using promise_type = typename base::promise_type;
1913  using promise_base_with_type = typename base::promise_base_with_type;
1915  using value_type = typename type::value_type;
1916  using tuple_type = typename type::tuple_type;
1917  using base::convert;
1919 
1922  template<typename Func, typename... FuncArgs>
1923  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
1924 
1927  template<typename Func, typename... FuncArgs>
1928  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
1929 
1930  template<typename Func>
1931  static inline type invoke(Func&& func, internal::monostate) noexcept {
1932  return invoke(std::forward<Func>(func));
1933  }
1934 
1936  template<typename Func, typename... FuncArgs>
1937  [[deprecated("Use invoke for varargs")]]
1938  static inline type apply(Func&& func, FuncArgs&&... args) noexcept {
1939  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1940  }
1941 
1942  static type current_exception_as_future() noexcept {
1944  }
1945 
1947  static type from_tuple(tuple_type&& value) {
1948  return type(ready_future_marker(), std::move(value));
1949  }
1951  static type from_tuple(const tuple_type& value) {
1952  return type(ready_future_marker(), value);
1953  }
1954 
1955 #if SEASTAR_API_LEVEL >= 5
1956  static type from_tuple(value_type&& value) {
1958  return type(ready_future_marker(), std::move(value));
1959  }
1961  static type from_tuple(const value_type& value) {
1962  return type(ready_future_marker(), value);
1963  }
1964 #endif
1965 private:
1969  template<typename Func>
1970  SEASTAR_CONCEPT( requires std::invocable<Func> )
1971  static void satisfy_with_result_of(promise_base_with_type&&, Func&& func);
1972 
1973  template <typename... U>
1974  friend class future;
1975 };
1976 
1977 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1978  : _future(future), _state(state) {
1979  _future->_promise = this;
1980 }
1981 
1982 template <typename... T>
1983 inline
1984 future<T...>
1986  assert(!this->_future && this->_state && !this->_task);
1987  return future<T...>(this);
1988 }
1989 
1990 template <typename... T>
1991 inline
1992 void promise<T...>::move_it(promise&& x) noexcept {
1993  if (this->_state == &x._local_state) {
1994  this->_state = &_local_state;
1995  new (&_local_state) future_state(std::move(x._local_state));
1996  }
1997 }
1998 
1999 template <typename... T, typename... A>
2000 inline
2001 future<T...> make_ready_future(A&&... value) noexcept {
2002  return future<T...>(ready_future_marker(), std::forward<A>(value)...);
2003 }
2004 
2005 template <typename... T>
2006 inline
2007 future<T...> make_exception_future(std::exception_ptr&& ex) noexcept {
2008  return future<T...>(exception_future_marker(), std::move(ex));
2009 }
2010 
2011 template <typename... T>
2012 inline
2013 future<T...> internal::make_exception_future(future_state_base&& state) noexcept {
2014  return future<T...>(exception_future_marker(), std::move(state));
2015 }
2016 
2017 template <typename... T>
2020 }
2021 
2022 void log_exception_trace() noexcept;
2023 
2030 template <typename... T, typename Exception>
2031 inline
2032 future<T...> make_exception_future(Exception&& ex) noexcept {
2033  log_exception_trace();
2034  return make_exception_future<T...>(std::make_exception_ptr(std::forward<Exception>(ex)));
2035 }
2036 
2037 template <typename... T, typename Exception>
2038 future<T...> make_exception_future_with_backtrace(Exception&& ex) noexcept {
2039  return make_exception_future<T...>(make_backtraced_exception_ptr<Exception>(std::forward<Exception>(ex)));
2040 }
2041 
2043 
2045 
2046 template<typename T>
2047 template<typename Func, typename... FuncArgs>
2048 typename futurize<T>::type futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
2049  try {
2050  using ret_t = decltype(std::apply(std::forward<Func>(func), std::move(args)));
2051  if constexpr (std::is_void_v<ret_t>) {
2052  std::apply(std::forward<Func>(func), std::move(args));
2053  return make_ready_future<>();
2054  } else if constexpr (is_future<ret_t>::value){
2055  return std::apply(std::forward<Func>(func), std::move(args));
2056  } else {
2057  return convert(std::apply(std::forward<Func>(func), std::move(args)));
2058  }
2059  } catch (...) {
2060  return current_exception_as_future();
2061  }
2062 }
2063 
2064 template<typename T>
2065 template<typename Func>
2066 SEASTAR_CONCEPT( requires std::invocable<Func> )
2067 void futurize<T>::satisfy_with_result_of(promise_base_with_type&& pr, Func&& func) {
2068  using ret_t = decltype(func());
2069  if constexpr (std::is_void_v<ret_t>) {
2070  func();
2071  pr.set_value();
2072  } else if constexpr (is_future<ret_t>::value) {
2073  func().forward_to(std::move(pr));
2074  } else {
2075  pr.set_value(func());
2076  }
2077 }
2078 
2079 template<typename T>
2080 template<typename Func, typename... FuncArgs>
2081 typename futurize<T>::type futurize<T>::invoke(Func&& func, FuncArgs&&... args) noexcept {
2082  try {
2083  using ret_t = decltype(func(std::forward<FuncArgs>(args)...));
2084  if constexpr (std::is_void_v<ret_t>) {
2085  func(std::forward<FuncArgs>(args)...);
2086  return make_ready_future<>();
2087  } else if constexpr (is_future<ret_t>::value) {
2088  return func(std::forward<FuncArgs>(args)...);
2089  } else {
2090  return convert(func(std::forward<FuncArgs>(args)...));
2091  }
2092  } catch (...) {
2093  return current_exception_as_future();
2094  }
2095 }
2096 
2097 template <typename T>
2098 template <typename Arg>
2099 inline
2100 future<T>
2104  return make_exception_future<T>(std::forward<Arg>(arg));
2105 }
2106 
2107 template <typename Arg>
2108 inline
2109 future<>
2113  return make_exception_future<>(std::forward<Arg>(arg));
2114 }
2115 
2116 template<typename Func, typename... Args>
2117 auto futurize_invoke(Func&& func, Args&&... args) noexcept {
2118  using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2119  return futurator::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2120 }
2121 
2122 template<typename Func, typename... Args>
2123 [[deprecated("Use futurize_invoke for varargs")]]
2124 auto futurize_apply(Func&& func, Args&&... args) noexcept {
2125  return futurize_invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2126 }
2127 
2128 template<typename Func, typename... Args>
2129 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept {
2130  using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2131  return futurator::apply(std::forward<Func>(func), std::move(args));
2132 }
2133 
2134 namespace internal {
2135 
2136 template <typename... T, typename U>
2137 inline
2138 void set_callback(future<T...>& fut, U* callback) noexcept {
2139  // It would be better to use continuation_base<T...> for U, but
2140  // then a derived class of continuation_base<T...> won't be matched
2141  return fut.set_callback(callback);
2142 }
2143 
2144 }
2145 
2146 
2148 
2149 }
seastar::promise::get_future
future< T... > get_future() noexcept
Gets the promise's associated future.
Definition: future.hh:1985
seastar::promise::set_exception
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:1013
seastar::futurize::invoke
static type invoke(Func &&func, FuncArgs &&... args) noexcept
seastar::future::then_wrapped
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:1580
seastar
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
seastar::current_exception_as_future
future< T... > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:2018
seastar::future::wait
void wait() noexcept
Definition: future.hh:1425
seastar::promise
promise - allows a future value to be made available at a later time.
Definition: future.hh:147
seastar::future::handle_exception_type
future< T... > handle_exception_type(Func &&func) noexcept
Handle the exception of a certain type carried by this future.
Definition: future.hh:1805
seastar::future::then_unpack
Result then_unpack(Func &&func) noexcept
Schedule a block of code to run when the future is ready, unpacking tuples.
Definition: future.hh:1509
seastar::make_ready_future
future< T... > make_ready_future(A &&... value) noexcept
Creates a future in an available, value state.
Definition: future.hh:2001
seastar::is_future
Check whether a type is a future.
Definition: future.hh:1042
seastar::broken_promise
Exception type for broken promises.
Definition: future.hh:202
seastar::memory::disable_failure_guard
Definition: alloc_failure_injector.hh:115
seastar::future::forward_to
void forward_to(promise< T... > &&pr) noexcept
Satisfy some promise object with this future as a result.
Definition: future.hh:1666
seastar::future_state_base::any
Definition: future.hh:432
seastar::future::failed
bool failed() const noexcept
Checks whether the future has failed.
Definition: future.hh:1444
seastar::futurize::apply
static type apply(Func &&func, FuncArgs &&... args) noexcept
Deprecated alias of invoke.
Definition: future.hh:1938
seastar::future::available
bool available() const noexcept
Checks whether the future is available.
Definition: future.hh:1436
seastar::future::finally_body
Definition: future.hh:1703
seastar::make_exception_future
future< T... > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:2007
seastar::futurize::apply
static type apply(Func &&func, std::tuple< FuncArgs... > &&args) noexcept
seastar::future_state_base::nested_exception_marker
Definition: future.hh:510
seastar::nested_exception
Definition: future.hh:45
seastar::exception_future_marker
Definition: future.hh:563
seastar::future::handle_exception
future< T... > handle_exception(Func &&func) noexcept
Handle the exception carried by this future.
Definition: future.hh:1783
seastar::future::future
future(future &&x) noexcept
Moves the future into a new object.
Definition: future.hh:1374
seastar::future_state_base::current_exception_as_future
friend future< U... > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:2018
seastar::futurize
Converts a type to a future type, if it isn't already.
Definition: future.hh:1055
seastar::function_traits
Definition: function_traits.hh:29
seastar::future::or_terminate
future or_terminate() noexcept
Terminate the program if this future fails.
Definition: future.hh:1744
seastar::future_for_get_promise_marker
Definition: future.hh:564
seastar::future::discard_result
future discard_result() noexcept
Discards the value carried by this future.
Definition: future.hh:1758
seastar::ready_future_marker
Definition: future.hh:562
seastar::future
A representation of a possibly not-yet-computed value.
Definition: future.hh:150
seastar::futurize::value_type
typename type::value_type value_type
The value tuple type associated with type.
Definition: future.hh:1915
seastar::future::then
Result then(Func &&func) noexcept
Schedule a block of code to run when the future is ready.
Definition: future.hh:1466
seastar::make_exception_future
future< T... > make_exception_future(Exception &&ex) noexcept
Creates a future in an available, failed state.
Definition: future.hh:2032
seastar::promise::set_to_current_exception
void set_to_current_exception() noexcept
Definition: future.hh:965
seastar::future< bool >::get0_return_type
typename future_state::get0_return_type get0_return_type
Definition: future.hh:1411
seastar::promise::set_exception
void set_exception(std::exception_ptr &&ex) noexcept
Marks the promise as failed.
Definition: future.hh:1000
seastar::futurize::from_tuple
static type from_tuple(const tuple_type &value)
Convert the tuple representation into a future.
Definition: future.hh:1951
seastar::future< bool >::value_type
internal::future_stored_type_t< T... > value_type
The data type carried by the future.
Definition: future.hh:1368
seastar::shared_future
Like future except the result can be waited for by many fibers.
Definition: future.hh:153
seastar::promise::promise
promise() noexcept
Constructs an empty promise.
Definition: future.hh:944
seastar::future::ignore_ready_future
void ignore_ready_future() noexcept
Ignore any result hold by this future.
Definition: future.hh:1824
seastar::futurize::from_tuple
static type from_tuple(tuple_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:1947
seastar::future_state_base::current_exception_future_marker
Definition: future.hh:508
seastar::noncopyable_function
Definition: noncopyable_function.hh:33
seastar::future::get
value_type && get()
gets the value returned by the computation
Definition: future.hh:1393
seastar::future_state_base
Definition: future.hh:416