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