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 #ifndef SEASTAR_MODULE
25 #include <cassert>
26 #include <atomic>
27 #include <cstdlib>
28 #include <cstring>
29 #include <functional>
30 #include <memory>
31 #include <stdexcept>
32 #include <type_traits>
33 #include <utility>
34 #endif
35 
36 #include <seastar/core/task.hh>
37 #include <seastar/core/thread_impl.hh>
38 #include <seastar/core/function_traits.hh>
39 #include <seastar/core/shard_id.hh>
40 #include <seastar/util/critical_alloc_section.hh>
41 #include <seastar/util/concepts.hh>
42 #include <seastar/util/noncopyable_function.hh>
43 #include <seastar/util/backtrace.hh>
44 #include <seastar/util/std-compat.hh>
45 #include <seastar/util/modules.hh>
46 
47 namespace seastar {
48 
49 struct nested_exception : public std::exception {
50  std::exception_ptr inner;
51  std::exception_ptr outer;
52  nested_exception(std::exception_ptr inner, std::exception_ptr outer) noexcept;
54  nested_exception(const nested_exception&) noexcept;
55  [[noreturn]] void rethrow_nested() const;
56  virtual const char* what() const noexcept override;
57 };
58 
82 
139 
145 
146 
149 SEASTAR_MODULE_EXPORT_BEGIN
150 template <class T = void>
151 class promise;
152 
153 template <class T>
154 class future;
155 
156 template <typename... T>
157 class shared_future;
158 
159 struct future_state_base;
160 
167 template <typename T = void, typename... A>
168 future<T> make_ready_future(A&&... value) noexcept;
169 
176 template <typename T = void>
177 future<T> make_exception_future(std::exception_ptr&& value) noexcept;
178 
179 template <typename T = void, typename Exception>
180 future<T> make_exception_future(Exception&& ex) noexcept;
181 
182 template <typename T = void>
183 future<T> make_exception_future(const std::exception_ptr& ex) noexcept {
184  return make_exception_future<T>(std::exception_ptr(ex));
185 }
186 
187 template <typename T = void>
188 future<T> make_exception_future(std::exception_ptr& ex) noexcept {
189  return make_exception_future<T>(static_cast<const std::exception_ptr&>(ex));
190 }
191 
192 template <typename T = void>
193 future<T> make_exception_future(const std::exception_ptr&& ex) noexcept {
194  // as ex is const, we cannot move it, but can copy it.
195  return make_exception_future<T>(std::exception_ptr(ex));
196 }
197 SEASTAR_MODULE_EXPORT_END
199 void engine_exit(std::exception_ptr eptr = {});
200 
201 void report_failed_future(const std::exception_ptr& ex) noexcept;
202 
203 void report_failed_future(const future_state_base& state) noexcept;
204 
206 
213 SEASTAR_MODULE_EXPORT
214 struct broken_promise : std::logic_error {
215  broken_promise();
216 };
217 
223 SEASTAR_MODULE_EXPORT
224 template <typename T = void>
226 
227 SEASTAR_MODULE_EXPORT
228 extern template
229 future<void> current_exception_as_future() noexcept;
230 
231 namespace internal {
232 template <class T = void>
233 class promise_base_with_type;
234 class promise_base;
235 
236 struct monostate {};
237 
238 template <typename... T>
239 struct future_stored_type;
240 
241 template <>
242 struct future_stored_type<> {
243  using type = monostate;
244 };
245 
246 template <typename T>
247 struct future_stored_type<T> {
248  using type = std::conditional_t<std::is_void_v<T>, internal::monostate, T>;
249 };
250 
251 template <typename... T>
252 using future_stored_type_t = typename future_stored_type<T...>::type;
253 
254 template<typename T>
255 using future_tuple_type_t = std::conditional_t<std::is_same_v<T, monostate>, std::tuple<>, std::tuple<T>>;
256 
257 // 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
258 // fails the build even if it is in the non enabled side of std::conditional.
259 template <typename T>
260 struct get0_return_type;
261 
262 template <>
263 struct get0_return_type<std::tuple<>> {
264  using type = void;
265  static type get0(std::tuple<>) { }
266 };
267 
268 template <typename T0, typename... T>
269 struct get0_return_type<std::tuple<T0, T...>> {
270  using type = T0;
271  static type get0(std::tuple<T0, T...> v) { return std::get<0>(std::move(v)); }
272 };
273 
274 template<typename T>
275 using maybe_wrap_ref = std::conditional_t<std::is_reference_v<T>, std::reference_wrapper<std::remove_reference_t<T>>, T>;
276 
284 template <typename T, bool is_trivial_class>
285 struct uninitialized_wrapper_base;
286 
287 template <typename T>
288 struct uninitialized_wrapper_base<T, false> {
289  using tuple_type = future_tuple_type_t<T>;
290  union any {
291  any() noexcept {}
292  ~any() {}
293  // T can be a reference, so wrap it.
294  maybe_wrap_ref<T> value;
295  } _v;
296 
297 public:
298  uninitialized_wrapper_base() noexcept = default;
299  template<typename... U>
300  std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>, void>
301  uninitialized_set(U&&... vs) {
302  new (&_v.value) maybe_wrap_ref<T>{T(std::forward<U>(vs)...)};
303  }
304  void uninitialized_set(tuple_type&& v) {
305  uninitialized_set(std::move(std::get<0>(v)));
306  }
307  void uninitialized_set(const tuple_type& v) {
308  uninitialized_set(std::get<0>(v));
309  }
310  maybe_wrap_ref<T>& uninitialized_get() {
311  return _v.value;
312  }
313  const maybe_wrap_ref<T>& uninitialized_get() const {
314  return _v.value;
315  }
316 };
317 
318 template <typename T> struct uninitialized_wrapper_base<T, true> : private T {
319  using tuple_type = future_tuple_type_t<T>;
320  uninitialized_wrapper_base() noexcept = default;
321  template<typename... U>
322  std::enable_if_t<!std::is_same_v<std::tuple<std::remove_cv_t<U>...>, std::tuple<tuple_type>>, void>
323  uninitialized_set(U&&... vs) {
324  new (this) T(std::forward<U>(vs)...);
325  }
326  void uninitialized_set(tuple_type&& v) {
327  if constexpr (std::tuple_size_v<tuple_type> != 0) {
328  uninitialized_set(std::move(std::get<0>(v)));
329  }
330  }
331  void uninitialized_set(const tuple_type& v) {
332  if constexpr (std::tuple_size_v<tuple_type> != 0) {
333  uninitialized_set(std::get<0>(v));
334  }
335  }
336  T& uninitialized_get() {
337  return *this;
338  }
339  const T& uninitialized_get() const {
340  return *this;
341  }
342 };
343 
344 template <typename T>
345 constexpr bool can_inherit =
346  (std::is_trivially_destructible_v<T> && std::is_trivially_constructible_v<T> &&
347  std::is_class_v<T> && !std::is_final_v<T>);
348 
349 // The objective is to avoid extra space for empty types like std::tuple<>. We could use std::is_empty_v, but it is
350 // better to check that both the constructor and destructor can be skipped.
351 template <typename T>
352 struct uninitialized_wrapper
353  : public uninitialized_wrapper_base<T, can_inherit<T>> {};
354 
355 template <typename T>
356 struct is_trivially_move_constructible_and_destructible {
357  static constexpr bool value = std::is_trivially_move_constructible_v<T> && std::is_trivially_destructible_v<T>;
358 };
359 
360 template <bool... v>
361 struct all_true : std::false_type {};
362 
363 template <>
364 struct all_true<> : std::true_type {};
365 
366 template <bool... v>
367 struct all_true<true, v...> : public all_true<v...> {};
368 
369 template<typename T>
370 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper;
371 
372 template <typename... T>
373 struct is_tuple_effectively_trivially_move_constructible_and_destructible_helper<std::tuple<T...>> {
374  static constexpr bool value = all_true<is_trivially_move_constructible_and_destructible<T>::value...>::value;
375 };
376 
377 template <typename T>
378 static constexpr bool is_tuple_effectively_trivially_move_constructible_and_destructible =
379  is_tuple_effectively_trivially_move_constructible_and_destructible_helper<T>::value;
380 
381 }
382 
383 //
384 // A future/promise pair maintain one logical value (a future_state).
385 // There are up to three places that can store it, but only one is
386 // active at any time.
387 //
388 // - in the promise _local_state member variable
389 //
390 // This is necessary because a promise is created first and there
391 // would be nowhere else to put the value.
392 //
393 // - in the future _state variable
394 //
395 // This is used anytime a future exists and then has not been called
396 // yet. This guarantees a simple access to the value for any code
397 // that already has a future.
398 //
399 // - in the task associated with the .then() clause (after .then() is called,
400 // if a value was not set)
401 //
402 //
403 // The promise maintains a pointer to the state, which is modified as
404 // the state moves to a new location due to events (such as .then() or
405 // get_future being called) or due to the promise or future being
406 // moved around.
407 //
408 
409 // non templated base class to reduce code duplication
410 SEASTAR_MODULE_EXPORT
412  static_assert(sizeof(std::exception_ptr) == sizeof(void*), "exception_ptr not a pointer");
413  enum class state : uintptr_t {
414  invalid = 0,
415  future = 1,
416  // the substate is intended to decouple the run-time prevention
417  // for duplicative result extraction (calling e.g. then() twice
418  // ends up in abandoned()) from the wrapped object's destruction
419  // handling which is orchestrated by future_state. Instead of
420  // creating a temporary future_state just for the sake of setting
421  // the "invalid" in the source instance, result_unavailable can
422  // be set to ensure future_state_base::available() returns false.
423  result_unavailable = 2,
424  result = 3,
425  exception_min = 4, // or anything greater
426  };
427  union any {
428  any() noexcept { st = state::future; }
429  any(state s) noexcept { st = s; }
430  void set_exception(std::exception_ptr&& e) noexcept {
431  new (&ex) std::exception_ptr(std::move(e));
432  assert(st >= state::exception_min);
433  }
434  any(std::exception_ptr&& e) noexcept {
435  set_exception(std::move(e));
436  }
437  // From a users' perspective, a result_unavailable is not valid
438  bool valid() const noexcept { return st != state::invalid && st != state::result_unavailable; }
439  bool available() const noexcept { return st == state::result || st >= state::exception_min; }
440  bool failed() const noexcept { return __builtin_expect(st >= state::exception_min, false); }
441  void check_failure() noexcept;
442  ~any() noexcept { }
443  std::exception_ptr take_exception() noexcept {
444  std::exception_ptr ret(std::move(ex));
445  // Unfortunately in libstdc++ ~exception_ptr is defined out of line. We know that it does nothing for
446  // moved out values, so we omit calling it. This is critical for the code quality produced for this
447  // function. Without the out of line call, gcc can figure out that both sides of the if produce
448  // identical code and merges them.if
449  // We don't make any assumptions about other c++ libraries.
450  // There is request with gcc to define it inline: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90295
451 #ifndef __GLIBCXX__
452  ex.~exception_ptr();
453 #endif
454  st = state::invalid;
455  return ret;
456  }
457  void move_it(any&& x) noexcept {
458 #ifdef __GLIBCXX__
459  // Unfortunally gcc cannot fully optimize the regular
460  // implementation:
461  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95014
462  // Given what we know about the libstdc++ implementation
463  // (see the comment in take_exception), we can just
464  // memmove and zero x. We use memmove to guarantee
465  // vaild results if &x == this.
466  memmove(static_cast<void*>(this), &x, sizeof(any));
467  x.st = state::invalid;
468 #else
469  if (x.st < state::exception_min) {
470  st = x.st;
471  x.st = state::invalid;
472  } else {
473  new (&ex) std::exception_ptr(x.take_exception());
474  }
475 #endif
476  }
477  any(any&& x) noexcept {
478  move_it(std::move(x));
479  }
480  any& operator=(any&& x) noexcept {
481  check_failure();
482  // If this is a self move assignment, check_failure
483  // guarantees that we don't have an exception and calling
484  // move_it is safe.
485  move_it(std::move(x));
486  return *this;
487  }
488  bool has_result() const noexcept {
489  return st == state::result || st == state::result_unavailable;
490  }
491  state st;
492  std::exception_ptr ex;
493  } _u;
494 
495  future_state_base() noexcept = default;
496  future_state_base(state st) noexcept : _u(st) { }
497  future_state_base(std::exception_ptr&& ex) noexcept : _u(std::move(ex)) { }
498  future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
499 
500  // We never need to destruct this polymorphicly, so we can make it
501  // protected instead of virtual.
502 protected:
508  ~future_state_base() noexcept = default;
509 
510  void rethrow_exception() &&;
511  void rethrow_exception() const&;
512 
513 public:
514 
515  bool valid() const noexcept { return _u.valid(); }
516  bool available() const noexcept { return _u.available(); }
517  bool failed() const noexcept { return _u.failed(); }
518 
519  void ignore() noexcept;
520 
521  void set_exception(std::exception_ptr&& ex) noexcept {
522  assert(_u.st == state::future);
523  _u.set_exception(std::move(ex));
524  }
525  future_state_base& operator=(future_state_base&& x) noexcept = default;
526  void set_exception(future_state_base&& state) noexcept {
527  assert(_u.st == state::future);
528  *this = std::move(state);
529  }
530  std::exception_ptr get_exception() && noexcept {
531  assert(_u.st >= state::exception_min);
532  // Move ex out so future::~future() knows we've handled it
533  return _u.take_exception();
534  }
535  const std::exception_ptr& get_exception() const& noexcept {
536  assert(_u.st >= state::exception_min);
537  return _u.ex;
538  }
539  template <typename U>
540  friend struct future_state;
541  template <typename U>
542  friend future<U> current_exception_as_future() noexcept;
543  template <typename U>
544  friend class future;
545  template <typename T>
546  friend struct futurize;
547 };
548 
549 void report_failed_future(future_state_base::any&& state) noexcept;
550 
551 inline void future_state_base::any::check_failure() noexcept {
552  if (failed()) {
553  report_failed_future(std::move(*this));
554  }
555 }
556 
560 
562 template <typename T>
563 struct future_state : public future_state_base, private internal::uninitialized_wrapper<T> {
564  static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible_v<T>;
565  static constexpr bool has_trivial_move_and_destroy = internal::is_trivially_move_constructible_and_destructible<T>::value;
566  static_assert(std::is_nothrow_move_constructible_v<T>,
567  "Types must be no-throw move constructible");
568  static_assert(std::is_nothrow_destructible_v<T>,
569  "Types must be no-throw destructible");
570  future_state() noexcept = default;
571  void move_it(future_state&& x) noexcept {
572  if constexpr (has_trivial_move_and_destroy) {
573 #pragma GCC diagnostic push
574  // This function may copy uninitialized memory, such as when
575  // creating an uninitialized promise and calling get_future()
576  // on it. Gcc 12 started to catch some simple cases of this
577  // at compile time, so we need to tell it that it's fine.
578 #pragma GCC diagnostic ignored "-Wuninitialized"
579  memmove(reinterpret_cast<char*>(&this->uninitialized_get()),
580  &x.uninitialized_get(),
581  internal::used_size<internal::maybe_wrap_ref<T>>::value);
582 #pragma GCC diagnostic pop
583  } else if (_u.has_result()) {
584  this->uninitialized_set(std::move(x.uninitialized_get()));
585  std::destroy_at(&x.uninitialized_get());
586  }
587  }
588 
589  [[gnu::always_inline]]
590  future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
591  move_it(std::move(x));
592  }
593 
594  void clear() noexcept {
595  if (_u.has_result()) {
596  std::destroy_at(&this->uninitialized_get());
597  } else {
598  _u.check_failure();
599  }
600  }
601  __attribute__((always_inline))
602  ~future_state() noexcept {
603  clear();
604  }
605  future_state& operator=(future_state&& x) noexcept {
606  clear();
607  future_state_base::operator=(std::move(x));
608  // If &x == this, _u.st is now state::invalid and so it is
609  // safe to call move_it.
610  move_it(std::move(x));
611  return *this;
612  }
613  template <typename... A>
614  future_state(ready_future_marker, A&&... a) noexcept : future_state_base(state::result) {
615  try {
616  this->uninitialized_set(std::forward<A>(a)...);
617  } catch (...) {
618  new (this) future_state(current_exception_future_marker());
619  }
620  }
621  template <typename... A>
622  void set(A&&... a) noexcept {
623  assert(_u.st == state::future);
624  new (this) future_state(ready_future_marker(), std::forward<A>(a)...);
625  }
626  future_state(exception_future_marker, std::exception_ptr&& ex) noexcept : future_state_base(std::move(ex)) { }
627  future_state(exception_future_marker, future_state_base&& state) noexcept : future_state_base(std::move(state)) { }
628  future_state(current_exception_future_marker m) noexcept : future_state_base(m) { }
629  future_state(nested_exception_marker m, future_state_base&& old) noexcept : future_state_base(m, std::move(old)) { }
630  future_state(nested_exception_marker m, future_state_base&& n, future_state_base&& old) noexcept : future_state_base(m, std::move(n), std::move(old)) { }
631  T&& get_value() && noexcept {
632  assert(_u.st == state::result);
633  return static_cast<T&&>(this->uninitialized_get());
634  }
635  T&& take_value() && noexcept {
636  assert(_u.st == state::result);
637  _u.st = state::result_unavailable;
638  return static_cast<T&&>(this->uninitialized_get());
639  }
640  template<typename U = T>
641  const std::enable_if_t<std::is_copy_constructible_v<U>, U>& get_value() const& noexcept(copy_noexcept) {
642  assert(_u.st == state::result);
643  return this->uninitialized_get();
644  }
645  T&& take() && {
646  assert(available());
647  if (_u.st >= state::exception_min) {
648  std::move(*this).rethrow_exception();
649  }
650  _u.st = state::result_unavailable;
651  return static_cast<T&&>(this->uninitialized_get());
652  }
653  T&& get() && {
654  assert(available());
655  if (_u.st >= state::exception_min) {
656  std::move(*this).rethrow_exception();
657  }
658  return static_cast<T&&>(this->uninitialized_get());
659  }
660  const T& get() const& {
661  assert(available());
662  if (_u.st >= state::exception_min) {
663  rethrow_exception();
664  }
665  return this->uninitialized_get();
666  }
667  using get0_return_type = typename internal::get0_return_type<internal::future_tuple_type_t<T>>::type;
668  static get0_return_type get0(T&& x) {
669  return internal::get0_return_type<T>::get0(std::move(x));
670  }
671 
672  get0_return_type get0() {
673  return std::move(*this).get();
674  }
675 };
676 
677 template <typename T = void>
678 class continuation_base : public task {
679 protected:
680  using future_state = seastar::future_state<internal::future_stored_type_t<T>>;
681  future_state _state;
682  using future_type = future<T>;
683  using promise_type = promise<T>;
684 public:
685  continuation_base() noexcept = default;
686  void set_state(future_state&& state) noexcept {
687  _state = std::move(state);
688  }
689  // This override of waiting_task() is needed here because there are cases
690  // when backtrace is obtained from the destructor of this class and objects
691  // of derived classes are already destroyed at that time. If we didn't
692  // have this override we would get a "pure virtual function call" exception.
693  virtual task* waiting_task() noexcept override { return nullptr; }
694  friend class internal::promise_base_with_type<T>;
695  friend class promise<T>;
696  friend class future<T>;
697 };
698 
699 // Given a future type, find the corresponding continuation_base.
700 template <typename Future>
701 struct continuation_base_from_future;
702 
703 template <typename... T>
704 struct continuation_base_from_future<future<T...>> {
705  using type = continuation_base<T...>;
706 };
707 
708 template <typename Future>
709 using continuation_base_from_future_t = typename continuation_base_from_future<Future>::type;
710 
711 template <typename Promise, typename T = void>
712 class continuation_base_with_promise : public continuation_base<T> {
713  friend class internal::promise_base_with_type<T>;
714 protected:
715  continuation_base_with_promise(Promise&& pr) noexcept : _pr(std::move(pr)) {
716  task::make_backtrace();
717  }
718  virtual task* waiting_task() noexcept override;
719  Promise _pr;
720 };
721 
722 template <typename Promise, typename Func, typename Wrapper, typename T = void>
723 struct continuation final : continuation_base_with_promise<Promise, T> {
724  // Func is the original function passed to then/then_wrapped. The
725  // Wrapper is a helper function that implements the specific logic
726  // needed by then/then_wrapped. We call the wrapper passing it the
727  // original function, promise and state.
728  // Note that if Func's move constructor throws, this will call
729  // std::unexpected. We could try to require Func to be nothrow
730  // move constructible, but that will cause a lot of churn. Since
731  // we can't support a failure to create a continuation, calling
732  // std::unexpected as close to the failure as possible is the best
733  // we can do.
734  continuation(Promise&& pr, Func&& func, Wrapper&& wrapper) noexcept
735  : continuation_base_with_promise<Promise, T>(std::move(pr))
736  , _func(std::move(func))
737  , _wrapper(std::move(wrapper)) {}
738  virtual void run_and_dispose() noexcept override {
739  try {
740  _wrapper(std::move(this->_pr), _func, std::move(this->_state));
741  } catch (...) {
742  this->_pr.set_to_current_exception();
743  }
744  delete this;
745  }
746  Func _func;
747  [[no_unique_address]] Wrapper _wrapper;
748 };
749 
750 namespace internal {
751 
752 template <typename T = void>
753 future<T> make_exception_future(future_state_base&& state) noexcept;
754 
755 template <typename... T, typename U>
756 void set_callback(future<T...>&& fut, U* callback) noexcept;
757 
758 class future_base;
759 
760 class promise_base {
761 protected:
762  enum class urgent { no, yes };
763  future_base* _future = nullptr;
764 
765  // This points to the future_state that is currently being
766  // used. See comment above the future_state struct definition for
767  // details.
768  future_state_base* _state;
769 
770  task* _task = nullptr;
771 #ifdef SEASTAR_DEBUG_PROMISE
772  int _task_shard = -1;
773 
774  void set_task(task* task) noexcept {
775  _task = task;
776  _task_shard = this_shard_id();
777  }
778  void assert_task_shard() const noexcept;
779 #else
780  void set_task(task* task) noexcept {
781  _task = task;
782  }
783  void assert_task_shard() const noexcept { }
784 #endif
785 
786  promise_base(const promise_base&) = delete;
787  promise_base(future_state_base* state) noexcept : _state(state) {}
788  promise_base(future_base* future, future_state_base* state) noexcept;
789  void move_it(promise_base&& x) noexcept;
790  promise_base(promise_base&& x) noexcept;
791 
792  void clear() noexcept;
793 
794  // We never need to destruct this polymorphicly, so we can make it
795  // protected instead of virtual
796  ~promise_base() noexcept {
797  clear();
798  }
799 
800  void operator=(const promise_base&) = delete;
801  promise_base& operator=(promise_base&& x) noexcept;
802 
803  template<urgent Urgent>
804  void make_ready() noexcept;
805 
806  template<typename T>
807  void set_exception_impl(T&& val) noexcept {
808  if (_state) {
809  _state->set_exception(std::move(val));
810  make_ready<urgent::no>();
811  } else {
812  // We get here if promise::get_future is called and the
813  // returned future is destroyed without creating a
814  // continuation.
815  // In older versions of seastar we would store a local
816  // copy of ex and warn in the promise destructor.
817  // Since there isn't any way for the user to clear
818  // the exception, we issue the warning from here.
819  report_failed_future(val);
820  }
821  }
822 
823  void set_exception(future_state_base&& state) noexcept {
824  set_exception_impl(std::move(state));
825  }
826 
827  void set_exception(std::exception_ptr&& ex) noexcept {
828  set_exception_impl(std::move(ex));
829  }
830 
831  void set_exception(const std::exception_ptr& ex) noexcept {
832  set_exception(std::exception_ptr(ex));
833  }
834 
835  template<typename Exception>
836  std::enable_if_t<!std::is_same_v<std::remove_reference_t<Exception>, std::exception_ptr>, void> set_exception(Exception&& e) noexcept {
837  set_exception(std::make_exception_ptr(std::forward<Exception>(e)));
838  }
839 
840  friend class future_base;
841  template <typename U> friend class seastar::future;
842 
843 public:
848  void set_to_current_exception() noexcept;
849 
851  task* waiting_task() const noexcept { return _task; }
852 };
853 
860 template <typename T>
861 class promise_base_with_type : protected internal::promise_base {
862 protected:
863  using future_state = seastar::future_state<future_stored_type_t<T>>;
864  future_state* get_state() noexcept {
865  return static_cast<future_state*>(_state);
866  }
867  static constexpr bool copy_noexcept = future_state::copy_noexcept;
868 public:
869  promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
870  promise_base_with_type(future<T>* future) noexcept : promise_base(future, &future->_state) { }
871  promise_base_with_type(promise_base_with_type&& x) noexcept = default;
872  promise_base_with_type(const promise_base_with_type&) = delete;
873  promise_base_with_type& operator=(promise_base_with_type&& x) noexcept = default;
874  void operator=(const promise_base_with_type&) = delete;
875 
876  void set_urgent_state(future_state&& state) noexcept {
877  auto* ptr = get_state();
878  // The state can be null if the corresponding future has been
879  // destroyed without producing a continuation.
880  if (ptr) {
881  // FIXME: This is a fairly expensive assert. It would be a
882  // good candidate for being disabled in release builds if
883  // we had such an assert.
884  assert(ptr->_u.st == future_state_base::state::future);
885  new (ptr) future_state(std::move(state));
886  make_ready<urgent::yes>();
887  }
888  }
889 
890  template <typename... A>
891  void set_value(A&&... a) noexcept {
892  if (auto *s = get_state()) {
893  s->set(std::forward<A>(a)...);
894  make_ready<urgent::no>();
895  }
896  }
897 
902  void set_to_current_exception() noexcept {
903  internal::promise_base::set_to_current_exception();
904  }
905 
907  using internal::promise_base::waiting_task;
908 
909 private:
910 
911  template <typename U>
912  friend class seastar::future;
913 
914  friend future_state;
915 };
916 }
918 
924 SEASTAR_MODULE_EXPORT
925 template <typename T>
926 class promise : private internal::promise_base_with_type<T> {
927  using future_state = typename internal::promise_base_with_type<T>::future_state;
928  future_state _local_state;
929 
930 public:
934  promise() noexcept : internal::promise_base_with_type<T>(&_local_state) {}
935 
937  void move_it(promise&& x) noexcept;
938  promise(promise&& x) noexcept : internal::promise_base_with_type<T>(std::move(x)) {
939  move_it(std::move(x));
940  }
941  promise(const promise&) = delete;
942  promise& operator=(promise&& x) noexcept {
943  internal::promise_base_with_type<T>::operator=(std::move(x));
944  // If this is a self-move, _state is now nullptr and it is
945  // safe to call move_it.
946  move_it(std::move(x));
947  return *this;
948  }
949  void operator=(const promise&) = delete;
950 
955  void set_to_current_exception() noexcept {
956  internal::promise_base::set_to_current_exception();
957  }
958 
960  using internal::promise_base::waiting_task;
961 
968  future<T> get_future() noexcept;
969 
981  template <typename... A>
982  void set_value(A&&... a) noexcept {
983  internal::promise_base_with_type<T>::set_value(std::forward<A>(a)...);
984  }
985 
990  void set_exception(std::exception_ptr&& ex) noexcept {
991  internal::promise_base::set_exception(std::move(ex));
992  }
993 
994  void set_exception(const std::exception_ptr& ex) noexcept {
995  internal::promise_base::set_exception(ex);
996  }
997 
1002  template<typename Exception>
1003  std::enable_if_t<!std::is_same_v<std::remove_reference_t<Exception>, std::exception_ptr>, void> set_exception(Exception&& e) noexcept {
1004  internal::promise_base::set_exception(std::forward<Exception>(e));
1005  }
1006 
1007  using internal::promise_base_with_type<T>::set_urgent_state;
1008 
1009  template <typename U>
1010  friend class future;
1011 };
1012 
1014 
1017 
1018 
1024 template <typename... T> struct is_future : std::false_type {};
1025 
1028 template <typename... T> struct is_future<future<T...>> : std::true_type {};
1029 
1031 
1032 
1036 SEASTAR_MODULE_EXPORT
1037 template <typename T>
1038 struct futurize;
1039 
1040 SEASTAR_CONCEPT(
1041 
1042 template <typename T>
1043 concept Future = is_future<T>::value;
1044 
1045 template <typename Func, typename... T>
1046 concept CanInvoke = std::invocable<Func, T...>;
1047 
1048 // Deprecated alias
1049 template <typename Func, typename... T>
1050 concept CanApply = CanInvoke<Func, T...>;
1051 
1052 template <typename Func, typename... T>
1053 concept CanApplyTuple
1054  = sizeof...(T) == 1
1055  && requires (Func func, std::tuple<T...> wrapped_val) {
1056  { std::apply(func, std::get<0>(std::move(wrapped_val))) };
1057  };
1058 
1059 // Deprecated, use std::is_invocable_r_v
1060 template <typename Func, typename Return, typename... T>
1061 concept InvokeReturns = requires (Func f, T... args) {
1062  { f(std::forward<T>(args)...) } -> std::same_as<Return>;
1063 };
1064 
1065 // Deprecated alias
1066 template <typename Func, typename Return, typename... T>
1067 concept ApplyReturns = InvokeReturns<Func, Return, T...>;
1068 
1069 template <typename Func, typename... T>
1070 concept InvokeReturnsAnyFuture = Future<std::invoke_result_t<Func, T...>>;
1071 
1072 // Deprecated alias
1073 template <typename Func, typename... T>
1074 concept ApplyReturnsAnyFuture = InvokeReturnsAnyFuture<Func, T...>;
1075 
1076 )
1077 
1079 
1080 // Converts a type to a future type, if it isn't already.
1081 template <typename T>
1082 using futurize_t = typename futurize<T>::type;
1083 
1085 
1086 template<typename Func, typename... Args>
1087 auto futurize_invoke(Func&& func, Args&&... args) noexcept;
1088 
1089 template<typename Func, typename... Args>
1090 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept;
1091 
1094 namespace internal {
1095 class future_base {
1096 protected:
1097  promise_base* _promise;
1098  future_base() noexcept : _promise(nullptr) {}
1099  future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
1100  _promise->_future = this;
1101  _promise->_state = state;
1102  }
1103 
1104  void move_it(future_base&& x, future_state_base* state) noexcept {
1105  _promise = x._promise;
1106  if (auto* p = _promise) {
1107  x.detach_promise();
1108  p->_future = this;
1109  p->_state = state;
1110  }
1111  }
1112 
1113  future_base(future_base&& x, future_state_base* state) noexcept {
1114  move_it(std::move(x), state);
1115  }
1116 
1117  void clear() noexcept {
1118  if (_promise) {
1119  detach_promise();
1120  }
1121  }
1122 
1123  ~future_base() noexcept {
1124  clear();
1125  }
1126 
1127  promise_base* detach_promise() noexcept {
1128  _promise->_state = nullptr;
1129  _promise->_future = nullptr;
1130  return std::exchange(_promise, nullptr);
1131  }
1132 
1133  void schedule(task* tws, future_state_base* state) noexcept {
1134  promise_base* p = detach_promise();
1135  p->_state = state;
1136  p->set_task(tws);
1137  }
1138 
1139  void do_wait() noexcept;
1140 
1141 #ifdef SEASTAR_COROUTINES_ENABLED
1142  void set_coroutine(task& coroutine) noexcept;
1143 #endif
1144 
1145  friend class promise_base;
1146 };
1147 
1148 template <typename Func, typename... T>
1149 struct future_result {
1150  using type = std::invoke_result_t<Func, T...>;
1151  using future_type = futurize_t<type>;
1152  using func_type = future_type (T&&...);
1153 };
1154 
1155 template <typename Func>
1156 struct future_result<Func, void> {
1157  using type = std::invoke_result_t<Func>;
1158  using future_type = futurize_t<type>;
1159  using func_type = future_type ();
1160 };
1161 
1162 template <typename Func, typename T>
1163 using future_result_t = typename future_result<Func, T>::type;
1164 
1165 template <typename Func, typename T>
1166 auto future_invoke(Func&& func, T&& v) {
1167  if constexpr (std::is_same_v<T, monostate>) {
1168  return std::invoke(std::forward<Func>(func));
1169  } else {
1170  return std::invoke(std::forward<Func>(func), std::forward<T>(v));
1171  }
1172 }
1173 
1174 template <typename Func, typename... T>
1175 struct result_of_apply {
1176  // no "type" member if not a function call signature or not a tuple
1177 };
1178 
1179 template <typename Func, typename... T>
1180 struct result_of_apply<Func, std::tuple<T...>> : std::invoke_result<Func, T...> {
1181  // Let std::invoke_result_t determine the result if the input is a tuple
1182 };
1183 
1184 template <typename Func, typename... T>
1185 using result_of_apply_t = typename result_of_apply<Func, T...>::type;
1186 
1187 }
1188 
1189 template <typename Promise, typename T>
1190 task* continuation_base_with_promise<Promise, T>::waiting_task() noexcept {
1191  return _pr.waiting_task();
1192 }
1193 
1236 SEASTAR_MODULE_EXPORT
1237 template <typename T>
1238 class [[nodiscard]] future : private internal::future_base {
1239  using future_state = seastar::future_state<internal::future_stored_type_t<T>>;
1240  future_state _state;
1241  static constexpr bool copy_noexcept = future_state::copy_noexcept;
1242 
1243 private:
1244  // This constructor creates a future that is not ready but has no
1245  // associated promise yet. The use case is to have a less flexible
1246  // but more efficient future/promise pair where we know that
1247  // promise::set_value cannot possibly be called without a matching
1248  // future and so that promise doesn't need to store a
1249  // future_state.
1251 
1252  future(promise<T>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
1253  template <typename... A>
1254  future(ready_future_marker m, A&&... a) noexcept : _state(m, std::forward<A>(a)...) { }
1256  future(future_state_base::nested_exception_marker m, future_state_base&& old) noexcept : _state(m, std::move(old)) {}
1257  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)) {}
1258  future(exception_future_marker m, std::exception_ptr&& ex) noexcept : _state(m, std::move(ex)) { }
1259  future(exception_future_marker m, future_state_base&& state) noexcept : _state(m, std::move(state)) { }
1260  [[gnu::always_inline]]
1261  explicit future(future_state&& state) noexcept
1262  : _state(std::move(state)) {
1263  }
1264  internal::promise_base_with_type<T> get_promise() noexcept {
1265  assert(!_promise);
1266  return internal::promise_base_with_type<T>(this);
1267  }
1268  internal::promise_base_with_type<T>* detach_promise() noexcept {
1269  return static_cast<internal::promise_base_with_type<T>*>(future_base::detach_promise());
1270  }
1271  void schedule(continuation_base<T>* tws) noexcept {
1272  future_base::schedule(tws, &tws->_state);
1273  }
1274  template <typename Pr, typename Func, typename Wrapper>
1275  void schedule(Pr&& pr, Func&& func, Wrapper&& wrapper) noexcept {
1276  // If this new throws a std::bad_alloc there is nothing that
1277  // can be done about it. The corresponding future is not ready
1278  // and we cannot break the chain. Since this function is
1279  // noexcept, it will call std::terminate if new throws.
1281  auto tws = new continuation<Pr, Func, Wrapper, T>(std::move(pr), std::move(func), std::move(wrapper));
1282  // In a debug build we schedule ready futures, but not in
1283  // other build modes.
1284 #ifdef SEASTAR_DEBUG
1285  if (_state.available()) {
1286  tws->set_state(get_available_state_ref());
1287  ::seastar::schedule(tws);
1288  return;
1289  }
1290 #endif
1291  schedule(tws);
1292  _state._u.st = future_state_base::state::invalid;
1293  }
1294 
1295  [[gnu::always_inline]]
1296  future_state&& get_available_state_ref() noexcept {
1297  if (_promise) {
1298  detach_promise();
1299  }
1300  return std::move(_state);
1301  }
1302 
1303  future<T> rethrow_with_nested(future_state_base&& n) noexcept {
1304  return future<T>(future_state_base::nested_exception_marker(), std::move(n), std::move(_state));
1305  }
1306 
1307  future<T> rethrow_with_nested() noexcept {
1308  return future<T>(future_state_base::nested_exception_marker(), std::move(_state));
1309  }
1310 
1311  template<typename... U>
1312  friend class shared_future;
1313 public:
1315  using value_type = internal::future_stored_type_t<T>;
1316  using tuple_type = internal::future_tuple_type_t<value_type>;
1320  [[gnu::always_inline]]
1321  future(future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1322  future(const future&) = delete;
1323  future& operator=(future&& x) noexcept {
1324  clear();
1325  move_it(std::move(x), &_state);
1326  _state = std::move(x._state);
1327  return *this;
1328  }
1329  void operator=(const future&) = delete;
1339  [[gnu::always_inline]]
1341  wait();
1342  return get_available_state_ref().take();
1343  }
1344 
1345  [[gnu::always_inline]]
1346  std::exception_ptr get_exception() noexcept {
1347  return get_available_state_ref().get_exception();
1348  }
1349 
1358  using get0_return_type = typename future_state::get0_return_type;
1359  get0_return_type get0() {
1360  return (get0_return_type)get();
1361  }
1362 
1368  void wait() noexcept {
1369  if (_state.available()) {
1370  return;
1371  }
1372  do_wait();
1373  }
1374 
1378  [[gnu::always_inline]]
1379  bool available() const noexcept {
1380  return _state.available();
1381  }
1382 
1386  [[gnu::always_inline]]
1387  bool failed() const noexcept {
1388  return _state.failed();
1389  }
1390 
1406  template <typename Func, typename Result = typename internal::future_result<Func, T>::future_type>
1407  SEASTAR_CONCEPT( requires std::invocable<Func, T>
1408  || (std::same_as<void, T> && std::invocable<Func>) )
1409  Result
1410  then(Func&& func) noexcept {
1411 #ifndef SEASTAR_TYPE_ERASE_MORE
1412  return then_impl(std::move(func));
1413 #else
1414  using func_type = typename internal::future_result<Func, T>::func_type;
1416  {
1418  ncf = noncopyable_function<func_type>([func = std::forward<Func>(func)](auto&&... args) mutable {
1419  return futurize_invoke(func, std::forward<decltype(args)>(args)...);
1420  });
1421  }
1422  return then_impl(std::move(ncf));
1423 #endif
1424  }
1425 
1445  template <typename Func, typename Result = futurize_t<internal::result_of_apply_t<Func, T>>>
1446  SEASTAR_CONCEPT( requires ::seastar::CanApplyTuple<Func, T>)
1447  Result
1448  then_unpack(Func&& func) noexcept {
1449  return then([func = std::forward<Func>(func)] (T&& tuple) mutable {
1450  // sizeof...(tuple) is required to be 1
1451  return std::apply(func, std::move(tuple));
1452  });
1453  }
1454 
1455 private:
1456 
1457  // Keep this simple so that Named Return Value Optimization is used.
1458  template <typename Func, typename Result>
1459  Result then_impl_nrvo(Func&& func) noexcept {
1461  typename futurator::type fut(future_for_get_promise_marker{});
1462  using pr_type = decltype(fut.get_promise());
1463  schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1464  if (state.failed()) {
1465  pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1466  } else {
1467  futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1468  // clang thinks that "state" is not used, below, for future<>.
1469  // Make it think it is used to avoid an unused-lambda-capture warning.
1470  (void)state;
1471  return internal::future_invoke(func, std::move(state).get_value());
1472  });
1473  }
1474  });
1475  return fut;
1476  }
1477 
1478  template <typename Func, typename Result = futurize_t<internal::future_result_t<Func, T>>>
1479  Result
1480  then_impl(Func&& func) noexcept {
1481 #ifndef SEASTAR_DEBUG
1482  using futurator = futurize<internal::future_result_t<Func, T>>;
1483  if (failed()) {
1484  return futurator::make_exception_future(static_cast<future_state_base&&>(get_available_state_ref()));
1485  } else if (available()) {
1486  return futurator::invoke(std::forward<Func>(func), get_available_state_ref().take_value());
1487  }
1488 #endif
1489  return then_impl_nrvo<Func, Result>(std::forward<Func>(func));
1490  }
1491 
1492 public:
1508  template <typename Func, typename FuncResult = std::invoke_result_t<Func, future>>
1509  SEASTAR_CONCEPT( requires std::invocable<Func, future> )
1510  futurize_t<FuncResult>
1511  then_wrapped(Func&& func) & noexcept {
1512  return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1513  }
1514 
1515  template <typename Func, typename FuncResult = std::invoke_result_t<Func, future&&>>
1516  SEASTAR_CONCEPT( requires std::invocable<Func, future&&> )
1517  futurize_t<FuncResult>
1518  then_wrapped(Func&& func) && noexcept {
1519  return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1520  }
1521 
1522 private:
1523 
1524  template <bool AsSelf, typename FuncResult, typename Func>
1525  futurize_t<FuncResult>
1526  then_wrapped_maybe_erase(Func&& func) noexcept {
1527 #ifndef SEASTAR_TYPE_ERASE_MORE
1528  return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1529 #else
1530  using futurator = futurize<FuncResult>;
1531  using WrapFuncResult = typename futurator::type;
1532  noncopyable_function<WrapFuncResult (future&&)> ncf;
1533  {
1534  memory::scoped_critical_alloc_section _;
1535  ncf = noncopyable_function<WrapFuncResult(future &&)>([func = std::forward<Func>(func)](future&& f) mutable {
1536  return futurator::invoke(func, std::move(f));
1537  });
1538  }
1539  return then_wrapped_common<AsSelf, WrapFuncResult>(std::move(ncf));
1540 #endif
1541  }
1542 
1543  // Keep this simple so that Named Return Value Optimization is used.
1544  template <typename FuncResult, typename Func>
1545  futurize_t<FuncResult>
1546  then_wrapped_nrvo(Func&& func) noexcept {
1547  using futurator = futurize<FuncResult>;
1548  typename futurator::type fut(future_for_get_promise_marker{});
1549  using pr_type = decltype(fut.get_promise());
1550  schedule(fut.get_promise(), std::move(func), [](pr_type&& pr, Func& func, future_state&& state) {
1551  futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1552  return func(future(std::move(state)));
1553  });
1554  });
1555  return fut;
1556  }
1557 
1558 
1559  template <bool AsSelf, typename FuncResult, typename Func>
1560  futurize_t<FuncResult>
1561  then_wrapped_common(Func&& func) noexcept {
1562 #ifndef SEASTAR_DEBUG
1563  using futurator = futurize<FuncResult>;
1564  if (available()) {
1565  if constexpr (AsSelf) {
1566  if (_promise) {
1567  detach_promise();
1568  }
1569  return futurator::invoke(std::forward<Func>(func), std::move(*this));
1570  } else {
1571  return futurator::invoke(std::forward<Func>(func), future(get_available_state_ref()));
1572  }
1573  }
1574 #endif
1575  return then_wrapped_nrvo<FuncResult, Func>(std::forward<Func>(func));
1576  }
1577 
1578  void forward_to(internal::promise_base_with_type<T>&& pr) noexcept {
1579  if (_state.available()) {
1580  pr.set_urgent_state(std::move(_state));
1581  } else {
1582  *detach_promise() = std::move(pr);
1583  }
1584  }
1585 
1586 public:
1597  void forward_to(promise<T>&& pr) noexcept {
1598  if (_state.available()) {
1599  pr.set_urgent_state(std::move(_state));
1600  } else if (&pr._local_state != pr._state) {
1601  // The only case when _state points to _local_state is
1602  // when get_future was never called. Given that pr will
1603  // soon be destroyed, we know get_future will never be
1604  // called and we can just ignore this request.
1605  *detach_promise() = std::move(pr);
1606  }
1607  }
1608 
1609 
1610 
1626  template <typename Func>
1627  SEASTAR_CONCEPT( requires std::invocable<Func> )
1628  future<T> finally(Func&& func) noexcept {
1629  return then_wrapped(finally_body<Func, is_future<std::invoke_result_t<Func>>::value>(std::forward<Func>(func)));
1630  }
1631 
1632 
1633  template <typename Func, bool FuncReturnsFuture>
1635 
1636  template <typename Func>
1637  struct finally_body<Func, true> {
1638  Func _func;
1639 
1640  finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1641  { }
1642 
1643  future<T> operator()(future<T>&& result) noexcept {
1644  return futurize_invoke(_func).then_wrapped([result = std::move(result)](auto&& f_res) mutable {
1645  if (!f_res.failed()) {
1646  return std::move(result);
1647  } else {
1648  return result.rethrow_with_nested(std::move(f_res._state));
1649  }
1650  });
1651  }
1652  };
1653 
1654  template <typename Func>
1655  struct finally_body<Func, false> {
1656  Func _func;
1657 
1658  finally_body(Func&& func) noexcept : _func(std::forward<Func>(func))
1659  { }
1660 
1661  future<T> operator()(future<T>&& result) noexcept {
1662  try {
1663  _func();
1664  return std::move(result);
1665  } catch (...) {
1666  return result.rethrow_with_nested();
1667  }
1668  };
1669  };
1670 
1675  future<> or_terminate() noexcept {
1676  return then_wrapped([] (auto&& f) {
1677  try {
1678  f.get();
1679  } catch (...) {
1680  engine_exit(std::current_exception());
1681  }
1682  });
1683  }
1684 
1690  // We need the generic variadic lambda, below, because then() behaves differently
1691  // when value_type is when_all_succeed_tuple
1692  return then([] (auto&&...) {});
1693  }
1694 
1708  template <typename Func>
1709  SEASTAR_CONCEPT( requires std::is_invocable_r_v<future<T> ,Func, std::exception_ptr>
1710  || (std::tuple_size_v<tuple_type> == 0 && std::is_invocable_r_v<void, Func, std::exception_ptr>)
1711  || (std::tuple_size_v<tuple_type> == 1 && std::is_invocable_r_v<T, Func, std::exception_ptr>)
1712  || (std::tuple_size_v<tuple_type> > 1 && std::is_invocable_r_v<tuple_type ,Func, std::exception_ptr>)
1713  )
1714  future<T> handle_exception(Func&& func) noexcept {
1715  return then_wrapped([func = std::forward<Func>(func)]
1716  (auto&& fut) mutable -> future<T> {
1717  if (!fut.failed()) {
1718  return make_ready_future<T>(fut.get());
1719  } else {
1720  return futurize_invoke(func, fut.get_exception());
1721  }
1722  });
1723  }
1724 
1735  template <typename Func>
1736  future<T> handle_exception_type(Func&& func) noexcept {
1737  using trait = function_traits<Func>;
1738  static_assert(trait::arity == 1, "func can take only one parameter");
1739  using ex_type = typename trait::template arg<0>::type;
1740  return then_wrapped([func = std::forward<Func>(func)]
1741  (auto&& fut) mutable -> future<T> {
1742  try {
1743  return make_ready_future<T>(fut.get());
1744  } catch(ex_type& ex) {
1745  return futurize_invoke(func, ex);
1746  }
1747  });
1748  }
1749 
1755  void ignore_ready_future() noexcept {
1756  _state.ignore();
1757  }
1758 
1759 #ifdef SEASTAR_COROUTINES_ENABLED
1760  using future_base::set_coroutine;
1761 #endif
1762 private:
1763  void set_task(task& t) noexcept {
1764  assert(_promise);
1765  _promise->set_task(&t);
1766  }
1767 
1768  void set_callback(continuation_base<T>* callback) noexcept {
1769  if (_state.available()) {
1770  callback->set_state(get_available_state_ref());
1771  ::seastar::schedule(callback);
1772  } else {
1773  assert(_promise);
1774  schedule(callback);
1775  }
1776 
1777  }
1778 
1780  template <typename U>
1781  friend class future;
1782  template <typename U>
1783  friend class promise;
1784  template <typename U>
1785  friend struct futurize;
1786  template <typename U>
1787  friend class internal::promise_base_with_type;
1788  template <typename U, typename... A>
1789  friend future<U> make_ready_future(A&&... value) noexcept;
1790  template <typename U>
1791  friend future<U> make_exception_future(std::exception_ptr&& ex) noexcept;
1792  template <typename U, typename Exception>
1793  friend future<U> make_exception_future(Exception&& ex) noexcept;
1794  template <typename U>
1795  friend future<U> internal::make_exception_future(future_state_base&& state) noexcept;
1796  template <typename U>
1797  friend future<U> current_exception_as_future() noexcept;
1798  template <typename... U, typename V>
1799  friend void internal::set_callback(future<U...>&&, V*) noexcept;
1801 };
1802 
1803 
1804 namespace internal {
1805 template <typename T>
1806 struct futurize_base {
1808  using type = future<T>;
1810  using promise_type = promise<T>;
1811  using promise_base_with_type = internal::promise_base_with_type<T>;
1812 
1814  static inline type convert(T&& value) { return make_ready_future<T>(std::move(value)); }
1815  static inline type convert(type&& value) { return std::move(value); }
1816 
1818  template <typename Arg>
1819  static inline type make_exception_future(Arg&& arg) noexcept;
1820 };
1821 
1822 template <>
1823 struct futurize_base<void> {
1824  using type = future<>;
1825  using promise_type = promise<>;
1826  using promise_base_with_type = internal::promise_base_with_type<>;
1827 
1828  static inline type convert(type&& value) {
1829  return std::move(value);
1830  }
1831  template <typename Arg>
1832  static inline type make_exception_future(Arg&& arg) noexcept;
1833 };
1834 
1835 template <typename T>
1836 struct futurize_base<future<T>> : public futurize_base<T> {};
1837 
1838 template <>
1839 struct futurize_base<future<>> : public futurize_base<void> {};
1840 }
1841 
1842 template <typename T>
1843 struct futurize : public internal::futurize_base<T> {
1844  using base = internal::futurize_base<T>;
1845  using type = typename base::type;
1846  using promise_type = typename base::promise_type;
1847  using promise_base_with_type = typename base::promise_base_with_type;
1849  using value_type = typename type::value_type;
1850  using tuple_type = typename type::tuple_type;
1851  using base::convert;
1852  using base::make_exception_future;
1853 
1856  template<typename Func, typename... FuncArgs>
1857  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
1858 
1861  template<typename Func, typename... FuncArgs>
1862  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
1863 
1864  template<typename Func>
1865  static inline type invoke(Func&& func, internal::monostate) noexcept {
1866  return invoke(std::forward<Func>(func));
1867  }
1868 
1870  template<typename Func, typename... FuncArgs>
1871  [[deprecated("Use invoke for varargs")]]
1872  static inline type apply(Func&& func, FuncArgs&&... args) noexcept {
1873  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1874  }
1875 
1876  static type current_exception_as_future() noexcept {
1878  }
1879 
1881  static type from_tuple(tuple_type&& value) {
1882  return type(ready_future_marker(), std::move(value));
1883  }
1885  static type from_tuple(const tuple_type& value) {
1886  return type(ready_future_marker(), value);
1887  }
1888 
1890  static type from_tuple(value_type&& value) {
1891  return type(ready_future_marker(), std::move(value));
1892  }
1894  static type from_tuple(const value_type& value) {
1895  return type(ready_future_marker(), value);
1896  }
1897 private:
1901  template<typename Func>
1902  SEASTAR_CONCEPT( requires std::invocable<Func> )
1903  static void satisfy_with_result_of(promise_base_with_type&&, Func&& func);
1904 
1905  template <typename U>
1906  friend class future;
1907 };
1908 
1909 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1910  : _future(future), _state(state) {
1911  _future->_promise = this;
1912 }
1913 
1914 template <typename T>
1915 inline
1916 future<T>
1918  assert(!this->_future && this->_state && !this->_task);
1919  return future<T>(this);
1920 }
1921 
1922 template <typename T>
1923 inline
1924 void promise<T>::move_it(promise&& x) noexcept {
1925  if (this->_state == &x._local_state) {
1926  this->_state = &_local_state;
1927  new (&_local_state) future_state(std::move(x._local_state));
1928  }
1929 }
1930 
1931 SEASTAR_MODULE_EXPORT_BEGIN
1932 template <typename T, typename... A>
1933 inline
1934 future<T> make_ready_future(A&&... value) noexcept {
1935  return future<T>(ready_future_marker(), std::forward<A>(value)...);
1936 }
1937 
1938 template <typename T>
1939 inline
1940 future<T> make_exception_future(std::exception_ptr&& ex) noexcept {
1941  return future<T>(exception_future_marker(), std::move(ex));
1942 }
1943 SEASTAR_MODULE_EXPORT_END
1944 
1945 template <typename T>
1946 inline
1947 future<T> internal::make_exception_future(future_state_base&& state) noexcept {
1948  return future<T>(exception_future_marker(), std::move(state));
1949 }
1950 
1951 SEASTAR_MODULE_EXPORT_BEGIN
1952 template <typename T>
1955 }
1956 
1957 void log_exception_trace() noexcept;
1958 
1965 template <typename T, typename Exception>
1966 inline
1967 future<T> make_exception_future(Exception&& ex) noexcept {
1968  log_exception_trace();
1969  return make_exception_future<T>(std::make_exception_ptr(std::forward<Exception>(ex)));
1970 }
1971 
1972 template <typename T, typename Exception>
1973 future<T> make_exception_future_with_backtrace(Exception&& ex) noexcept {
1974  return make_exception_future<T>(make_backtraced_exception_ptr<Exception>(std::forward<Exception>(ex)));
1975 }
1976 SEASTAR_MODULE_EXPORT_END
1977 
1979 
1981 
1982 template<typename T>
1983 template<typename Func, typename... FuncArgs>
1984 typename futurize<T>::type futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1985  try {
1986  using ret_t = decltype(std::apply(std::forward<Func>(func), std::move(args)));
1987  if constexpr (std::is_void_v<ret_t>) {
1988  std::apply(std::forward<Func>(func), std::move(args));
1989  return make_ready_future<>();
1990  } else if constexpr (is_future<ret_t>::value){
1991  return std::apply(std::forward<Func>(func), std::move(args));
1992  } else {
1993  return convert(std::apply(std::forward<Func>(func), std::move(args)));
1994  }
1995  } catch (...) {
1996  return current_exception_as_future();
1997  }
1998 }
1999 
2000 template<typename T>
2001 template<typename Func>
2002 SEASTAR_CONCEPT( requires std::invocable<Func> )
2003 void futurize<T>::satisfy_with_result_of(promise_base_with_type&& pr, Func&& func) {
2004  using ret_t = decltype(func());
2005  if constexpr (std::is_void_v<ret_t>) {
2006  func();
2007  pr.set_value();
2008  } else if constexpr (is_future<ret_t>::value) {
2009  func().forward_to(std::move(pr));
2010  } else {
2011  pr.set_value(func());
2012  }
2013 }
2014 
2015 template<typename T>
2016 template<typename Func, typename... FuncArgs>
2017 typename futurize<T>::type futurize<T>::invoke(Func&& func, FuncArgs&&... args) noexcept {
2018  try {
2019  using ret_t = decltype(func(std::forward<FuncArgs>(args)...));
2020  if constexpr (std::is_void_v<ret_t>) {
2021  func(std::forward<FuncArgs>(args)...);
2022  return make_ready_future<>();
2023  } else if constexpr (is_future<ret_t>::value) {
2024  return func(std::forward<FuncArgs>(args)...);
2025  } else {
2026  return convert(func(std::forward<FuncArgs>(args)...));
2027  }
2028  } catch (...) {
2029  return current_exception_as_future();
2030  }
2031 }
2032 
2033 template <typename T>
2034 template <typename Arg>
2035 inline
2036 future<T>
2037 internal::futurize_base<T>::make_exception_future(Arg&& arg) noexcept {
2038  using ::seastar::make_exception_future;
2039  using ::seastar::internal::make_exception_future;
2040  return make_exception_future<T>(std::forward<Arg>(arg));
2041 }
2042 
2043 template <typename Arg>
2044 inline
2045 future<>
2046 internal::futurize_base<void>::make_exception_future(Arg&& arg) noexcept {
2047  using ::seastar::make_exception_future;
2048  using ::seastar::internal::make_exception_future;
2049  return make_exception_future<>(std::forward<Arg>(arg));
2050 }
2051 
2052 template<typename Func, typename... Args>
2053 auto futurize_invoke(Func&& func, Args&&... args) noexcept {
2054  using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2055  return futurator::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2056 }
2057 
2058 template<typename Func, typename... Args>
2059 [[deprecated("Use futurize_invoke for varargs")]]
2060 auto futurize_apply(Func&& func, Args&&... args) noexcept {
2061  return futurize_invoke(std::forward<Func>(func), std::forward<Args>(args)...);
2062 }
2063 
2064 template<typename Func, typename... Args>
2065 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept {
2066  using futurator = futurize<std::invoke_result_t<Func, Args&&...>>;
2067  return futurator::apply(std::forward<Func>(func), std::move(args));
2068 }
2069 
2070 namespace internal {
2071 
2072 template <typename... T, typename U>
2073 inline
2074 void set_callback(future<T...>&& fut, U* callback) noexcept {
2075  // It would be better to use continuation_base<T...> for U, but
2076  // then a derived class of continuation_base<T...> won't be matched
2077  return std::move(fut).set_callback(callback);
2078 }
2079 
2080 }
2081 
2082 
2084 
2085 }
A representation of a possibly not-yet-computed value.
Definition: future.hh:1238
void wait() noexcept
Definition: future.hh:1368
internal::future_stored_type_t< T > value_type
The data type carried by the future.
Definition: future.hh:1315
Result then(Func &&func) noexcept
Schedule a block of code to run when the future is ready.
Definition: future.hh:1410
bool failed() const noexcept
Checks whether the future has failed.
Definition: future.hh:1387
bool available() const noexcept
Checks whether the future is available.
Definition: future.hh:1379
typename future_state::get0_return_type get0_return_type
Definition: future.hh:1358
void forward_to(promise< T > &&pr) noexcept
Satisfy some promise object with this future as a result.
Definition: future.hh:1597
futurize_t< FuncResult > then_wrapped(Func &&func) &noexcept
Schedule a block of code to run when the future is ready, allowing for exception handling.
Definition: future.hh:1511
Result then_unpack(Func &&func) noexcept
Schedule a block of code to run when the future is ready, unpacking tuples.
Definition: future.hh:1448
future(future &&x) noexcept
Moves the future into a new object.
Definition: future.hh:1321
value_type && get()
gets the value returned by the computation
Definition: future.hh:1340
future< T > handle_exception_type(Func &&func) noexcept
Handle the exception of a certain type carried by this future.
Definition: future.hh:1736
future discard_result() noexcept
Discards the value carried by this future.
Definition: future.hh:1689
future or_terminate() noexcept
Terminate the program if this future fails.
Definition: future.hh:1675
void ignore_ready_future() noexcept
Ignore any result hold by this future.
Definition: future.hh:1755
Definition: future.hh:1634
promise - allows a future value to be made available at a later time.
Definition: future.hh:926
void set_to_current_exception() noexcept
Definition: future.hh:955
void set_value(A &&... a) noexcept
Sets the promises value.
Definition: future.hh:982
void set_exception(std::exception_ptr &&ex) noexcept
Marks the promise as failed.
Definition: future.hh:990
promise() noexcept
Constructs an empty promise.
Definition: future.hh:934
std::enable_if_t<!std::is_same_v< std::remove_reference_t< Exception >, std::exception_ptr >, void > set_exception(Exception &&e) noexcept
Marks the promise as failed.
Definition: future.hh:1003
Like future except the result can be waited for by many fibers.
Definition: shared_future.hh:108
Definition: task.hh:35
future< T > make_ready_future(A &&... value) noexcept
Creates a future in an available, value state.
Definition: future.hh:1934
future< T > get_future() noexcept
Gets the promise's associated future.
Definition: future.hh:1917
future< T > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1940
future< T > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:1953
void move_it(promise &&x) noexcept
Moves a promise object.
Definition: future.hh:1924
Definition: future.hh:558
Definition: future.hh:557
Definition: critical_alloc_section.hh:80
Seastar API namespace.
Definition: abort_on_ebadf.hh:26
SEASTAR_MODULE_EXPORT_BEGIN shard_id this_shard_id() noexcept
Returns shard_id of the of the current shard.
Definition: shard_id.hh:50
Definition: noncopyable_function.hh:37
Definition: function_traits.hh:62
Exception type for broken promises.
Definition: future.hh:214
Definition: future.hh:411
friend future< U > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:1953
Converts a type to a future type, if it isn't already.
Definition: future.hh:1843
static type apply(Func &&func, FuncArgs &&... args) noexcept
Deprecated alias of invoke.
Definition: future.hh:1872
static type from_tuple(tuple_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:1881
static type from_tuple(value_type &&value)
Convert the tuple representation into a future.
Definition: future.hh:1890
static type apply(Func &&func, std::tuple< FuncArgs... > &&args) noexcept
static type from_tuple(const value_type &value)
Convert the tuple representation into a future.
Definition: future.hh:1894
static type from_tuple(const tuple_type &value)
Convert the tuple representation into a future.
Definition: future.hh:1885
typename type::value_type value_type
The value tuple type associated with type.
Definition: future.hh:1849
static type invoke(Func &&func, FuncArgs &&... args) noexcept
Check whether a type is a future.
Definition: future.hh:1024
Definition: future.hh:49
Definition: future.hh:427