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/apply.hh>
25 #include <seastar/core/task.hh>
26 #include <seastar/core/preempt.hh>
27 #include <seastar/core/thread_impl.hh>
28 #include <stdexcept>
29 #include <atomic>
30 #include <memory>
31 #include <type_traits>
32 #include <assert.h>
33 #include <cstdlib>
34 #include <seastar/core/function_traits.hh>
35 #include <seastar/util/alloc_failure_injector.hh>
36 #include <seastar/util/attribute-compat.hh>
37 #include <seastar/util/concepts.hh>
38 #include <seastar/util/noncopyable_function.hh>
39 
40 #if __cplusplus > 201703L
41 #include <version>
42 #endif
43 
44 namespace seastar {
45 
69 
74 
75 
78 
79 template <class... T>
80 class promise;
81 
82 template <class... T>
83 class future;
84 
85 template <typename... T>
87 
88 struct future_state_base;
89 
96 template <typename... T, typename... A>
97 future<T...> make_ready_future(A&&... value) noexcept;
98 
105 template <typename... T>
106 future<T...> make_exception_future(std::exception_ptr&& value) noexcept;
107 
108 template <typename... T>
109 future<T...> make_exception_future(const std::exception_ptr& ex) noexcept {
110  return make_exception_future<T...>(std::exception_ptr(ex));
111 }
112 
113 template <typename... T>
114 future<T...> make_exception_future(std::exception_ptr& ex) noexcept {
115  return make_exception_future<T...>(static_cast<const std::exception_ptr&>(ex));
116 }
117 
119 void engine_exit(std::exception_ptr eptr = {});
120 
121 void report_failed_future(const std::exception_ptr& ex) noexcept;
122 
123 void report_failed_future(const future_state_base& state) noexcept;
124 
126 
133 struct broken_promise : std::logic_error {
134  broken_promise();
135 };
136 
142 template <typename... T>
143 future<T...> current_exception_as_future() noexcept;
144 
145 extern template
147 
148 namespace internal {
149 template <class... T>
150 class promise_base_with_type;
151 
152 // 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
153 // fails the build even if it is in the non enabled side of std::conditional.
154 template <typename... T>
155 struct get0_return_type {
156  using type = void;
157  static type get0(std::tuple<T...> v) { }
158 };
159 
160 template <typename T0, typename... T>
161 struct get0_return_type<T0, T...> {
162  using type = T0;
163  static type get0(std::tuple<T0, T...> v) { return std::get<0>(std::move(v)); }
164 };
165 
173 template <typename T, bool is_trivial_class>
174 struct uninitialized_wrapper_base;
175 
176 template <typename T>
177 struct uninitialized_wrapper_base<T, false> {
178  union any {
179  any() {}
180  ~any() {}
181  T value;
182  } _v;
183 
184 public:
185  template<typename... U>
186  void uninitialized_set(U&&... vs) {
187  new (&_v.value) T(std::forward<U>(vs)...);
188  }
189  T& uninitialized_get() {
190  return _v.value;
191  }
192  const T& uninitialized_get() const {
193  return _v.value;
194  }
195 };
196 
197 template <typename T> struct uninitialized_wrapper_base<T, true> : private T {
198  template<typename... U>
199  void uninitialized_set(U&&... vs) {
200  new (this) T(std::forward<U>(vs)...);
201  }
202  T& uninitialized_get() {
203  return *this;
204  }
205  const T& uninitialized_get() const {
206  return *this;
207  }
208 };
209 
210 template <typename T>
211 constexpr bool can_inherit =
212 #ifdef _LIBCPP_VERSION
213 // We expect std::tuple<> to be trivially constructible and
214 // destructible. That is not the case with libc++
215 // (https://bugs.llvm.org/show_bug.cgi?id=41714). We could avoid this
216 // optimization when using libc++ and relax the asserts, but
217 // inspection suggests that std::tuple<> is trivial, it is just not
218 // marked as such.
219  std::is_same<std::tuple<>, T>::value ||
220 #endif
221  (std::is_trivially_destructible<T>::value && std::is_trivially_constructible<T>::value &&
222  std::is_class<T>::value && !std::is_final<T>::value);
223 
224 // The objective is to avoid extra space for empty types like std::tuple<>. We could use std::is_empty_v, but it is
225 // better to check that both the constructor and destructor can be skipped.
226 template <typename T>
227 struct uninitialized_wrapper
228  : public uninitialized_wrapper_base<T, can_inherit<T>> {};
229 
230 template <typename T>
231 struct is_trivially_move_constructible_and_destructible {
232  static constexpr bool value = std::is_trivially_move_constructible<T>::value && std::is_trivially_destructible<T>::value;
233 };
234 
235 template <bool... v>
236 struct all_true : std::false_type {};
237 
238 template <>
239 struct all_true<> : std::true_type {};
240 
241 template <bool... v>
242 struct all_true<true, v...> : public all_true<v...> {};
243 }
244 
245 //
246 // A future/promise pair maintain one logical value (a future_state).
247 // There are up to three places that can store it, but only one is
248 // active at any time.
249 //
250 // - in the promise _local_state member variable
251 //
252 // This is necessary because a promise is created first and there
253 // would be nowhere else to put the value.
254 //
255 // - in the future _state variable
256 //
257 // This is used anytime a future exists and then has not been called
258 // yet. This guarantees a simple access to the value for any code
259 // that already has a future.
260 //
261 // - in the task associated with the .then() clause (after .then() is called,
262 // if a value was not set)
263 //
264 //
265 // The promise maintains a pointer to the state, which is modified as
266 // the state moves to a new location due to events (such as .then() or
267 // get_future being called) or due to the promise or future being
268 // moved around.
269 //
270 
271 // non templated base class to reduce code duplication
273  static_assert(sizeof(std::exception_ptr) == sizeof(void*), "exception_ptr not a pointer");
274  enum class state : uintptr_t {
275  invalid = 0,
276  future = 1,
277  // the substate is intended to decouple the run-time prevention
278  // for duplicative result extraction (calling e.g. then() twice
279  // ends up in abandoned()) from the wrapped object's destruction
280  // handling which is orchestrated by future_state. Instead of
281  // creating a temporary future_state just for the sake of setting
282  // the "invalid" in the source instance, result_unavailable can
283  // be set to ensure future_state_base::available() returns false.
284  result_unavailable = 2,
285  result = 3,
286  exception_min = 4, // or anything greater
287  };
288  union any {
289  any() noexcept { st = state::future; }
290  any(state s) noexcept { st = s; }
291  void set_exception(std::exception_ptr&& e) noexcept {
292  new (&ex) std::exception_ptr(std::move(e));
293  assert(st >= state::exception_min);
294  }
295  any(std::exception_ptr&& e) noexcept {
296  set_exception(std::move(e));
297  }
298  bool valid() const noexcept { return st != state::invalid; }
299  bool available() const noexcept { return st == state::result || st >= state::exception_min; }
300  bool failed() const noexcept { return __builtin_expect(st >= state::exception_min, false); }
301  void check_failure() noexcept {
302  if (failed()) {
303  report_failed_future(take_exception());
304  }
305  }
306  ~any() noexcept {
307  check_failure();
308  }
309  std::exception_ptr take_exception() noexcept {
310  std::exception_ptr ret(std::move(ex));
311  // Unfortunately in libstdc++ ~exception_ptr is defined out of line. We know that it does nothing for
312  // moved out values, so we omit calling it. This is critical for the code quality produced for this
313  // function. Without the out of line call, gcc can figure out that both sides of the if produce
314  // identical code and merges them.if
315  // We don't make any assumptions about other c++ libraries.
316  // There is request with gcc to define it inline: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90295
317 #ifndef __GLIBCXX__
318  ex.~exception_ptr();
319 #endif
320  st = state::invalid;
321  return ret;
322  }
323  void move_it(any&& x) noexcept {
324 #ifdef __GLIBCXX__
325  // Unfortunally gcc cannot fully optimize the regular
326  // implementation:
327  // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95014
328  // Given what we know about the libstdc++ implementation
329  // (see the comment in take_exception), we can just
330  // memmove and zero x. We use memmove to guarantee
331  // vaild results if &x == this.
332  memmove(static_cast<void*>(this), &x, sizeof(any));
333  x.st = state::invalid;
334 #else
335  if (x.st < state::exception_min) {
336  st = x.st;
337  x.st = state::invalid;
338  } else {
339  new (&ex) std::exception_ptr(x.take_exception());
340  }
341 #endif
342  }
343  any(any&& x) noexcept {
344  move_it(std::move(x));
345  }
346  any& operator=(any&& x) noexcept {
347  check_failure();
348  // If this is a self move assignment, check_failure
349  // guarantees that we don't have an exception and calling
350  // move_it is safe.
351  move_it(std::move(x));
352  return *this;
353  }
354  bool has_result() const {
355  return st == state::result || st == state::result_unavailable;
356  }
357  state st;
358  std::exception_ptr ex;
359  } _u;
360 
361  future_state_base() noexcept { }
362  future_state_base(state st) noexcept : _u(st) { }
363  future_state_base(std::exception_ptr&& ex) noexcept : _u(std::move(ex)) { }
364  future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
365 
366  // We never need to destruct this polymorphicly, so we can make it
367  // protected instead of virtual.
368 protected:
369  ~future_state_base() noexcept = default;
370 
371 public:
372 
373  bool valid() const noexcept { return _u.valid(); }
374  bool available() const noexcept { return _u.available(); }
375  bool failed() const noexcept { return _u.failed(); }
376 
377  void set_to_broken_promise() noexcept;
378 
379  void ignore() noexcept;
380 
381  void set_exception(std::exception_ptr&& ex) noexcept {
382  assert(_u.st == state::future);
383  _u.set_exception(std::move(ex));
384  }
385  future_state_base& operator=(future_state_base&& x) noexcept = default;
386  void set_exception(future_state_base&& state) noexcept {
387  assert(_u.st == state::future);
388  *this = std::move(state);
389  }
390  std::exception_ptr get_exception() && noexcept {
391  assert(_u.st >= state::exception_min);
392  // Move ex out so future::~future() knows we've handled it
393  return _u.take_exception();
394  }
395  const std::exception_ptr& get_exception() const& noexcept {
396  assert(_u.st >= state::exception_min);
397  return _u.ex;
398  }
399 
400  static future_state_base current_exception() noexcept;
401 
402  template <typename... U>
403  friend future<U...> current_exception_as_future() noexcept;
404  template <typename... U>
405  friend struct future_state;
406 };
407 
411 
413 template <typename... T>
414 struct future_state : public future_state_base, private internal::uninitialized_wrapper<std::tuple<T...>> {
415  static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible<std::tuple<T...>>::value;
416  static constexpr bool has_trivial_move_and_destroy =
417  internal::all_true<internal::is_trivially_move_constructible_and_destructible<T>::value...>::value;
418  static_assert(std::is_nothrow_move_constructible<std::tuple<T...>>::value,
419  "Types must be no-throw move constructible");
420  static_assert(std::is_nothrow_destructible<std::tuple<T...>>::value,
421  "Types must be no-throw destructible");
422  future_state() noexcept {}
423  void move_it(future_state&& x) noexcept {
424  if (has_trivial_move_and_destroy) {
425 #pragma GCC diagnostic push
426 // Unfortunately gcc 8 warns about the memcpy of uninitialized
427 // memory. We can drop this when we drop support for gcc 8.
428 #pragma GCC diagnostic ignored "-Wuninitialized"
429  memmove(reinterpret_cast<char*>(&this->uninitialized_get()),
430  &x.uninitialized_get(),
431  internal::used_size<std::tuple<T...>>::value);
432 #pragma GCC diagnostic pop
433  } else if (_u.has_result()) {
434  this->uninitialized_set(std::move(x.uninitialized_get()));
435  x.uninitialized_get().~tuple();
436  }
437  }
438 
439  [[gnu::always_inline]]
440  future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
441  move_it(std::move(x));
442  }
443 
444  void clear() noexcept {
445  if (_u.has_result()) {
446  this->uninitialized_get().~tuple();
447  }
448  }
449  __attribute__((always_inline))
450  ~future_state() noexcept {
451  clear();
452  }
453  future_state& operator=(future_state&& x) noexcept {
454  clear();
455  future_state_base::operator=(std::move(x));
456  // If &x == this, _u.st is now state::invalid and so it is
457  // safe to call move_it.
458  move_it(std::move(x));
459  return *this;
460  }
461  template <typename... A>
462  future_state(ready_future_marker, A&&... a) noexcept : future_state_base(state::result) {
463  try {
464  this->uninitialized_set(std::forward<A>(a)...);
465  } catch (...) {
466  new (this) future_state(exception_future_marker(), current_exception());
467  }
468  }
469  template <typename... A>
470  void set(A&&... a) {
471  assert(_u.st == state::future);
472  new (this) future_state(ready_future_marker(), std::forward<A>(a)...);
473  }
474  future_state(exception_future_marker m, std::exception_ptr&& ex) noexcept : future_state_base(std::move(ex)) { }
475  future_state(exception_future_marker m, future_state_base&& state) noexcept : future_state_base(std::move(state)) { }
476  std::tuple<T...>&& get_value() && noexcept {
477  assert(_u.st == state::result);
478  return std::move(this->uninitialized_get());
479  }
480  std::tuple<T...>&& take_value() && noexcept {
481  assert(_u.st == state::result);
482  _u.st = state::result_unavailable;
483  return std::move(this->uninitialized_get());
484  }
485  template<typename U = std::tuple<T...>>
486  const std::enable_if_t<std::is_copy_constructible<U>::value, U>& get_value() const& noexcept(copy_noexcept) {
487  assert(_u.st == state::result);
488  return this->uninitialized_get();
489  }
490  std::tuple<T...>&& take() && {
491  assert(available());
492  if (_u.st >= state::exception_min) {
493  // Move ex out so future::~future() knows we've handled it
494  std::rethrow_exception(std::move(*this).get_exception());
495  }
496  _u.st = state::result_unavailable;
497  return std::move(this->uninitialized_get());
498  }
499  std::tuple<T...>&& get() && {
500  assert(available());
501  if (_u.st >= state::exception_min) {
502  // Move ex out so future::~future() knows we've handled it
503  std::rethrow_exception(std::move(*this).get_exception());
504  }
505  return std::move(this->uninitialized_get());
506  }
507  const std::tuple<T...>& get() const& {
508  assert(available());
509  if (_u.st >= state::exception_min) {
510  std::rethrow_exception(_u.ex);
511  }
512  return this->uninitialized_get();
513  }
514  using get0_return_type = typename internal::get0_return_type<T...>::type;
515  static get0_return_type get0(std::tuple<T...>&& x) {
516  return internal::get0_return_type<T...>::get0(std::move(x));
517  }
518 };
519 
520 template <typename... T>
521 class continuation_base : public task {
522 protected:
523  future_state<T...> _state;
524  using future_type = future<T...>;
525  using promise_type = promise<T...>;
526 public:
527  continuation_base() = default;
528  explicit continuation_base(future_state<T...>&& state) : _state(std::move(state)) {}
529  void set_state(future_state<T...>&& state) {
530  _state = std::move(state);
531  }
532  friend class internal::promise_base_with_type<T...>;
533  friend class promise<T...>;
534  friend class future<T...>;
535 };
536 
537 template <typename Promise, typename... T>
538 class continuation_base_with_promise : public continuation_base<T...> {
539 protected:
540  continuation_base_with_promise(Promise&& pr, future_state<T...>&& state)
541  : continuation_base<T...>(std::move(state)), _pr(std::move(pr)) {}
542  continuation_base_with_promise(Promise&& pr) : _pr(std::move(pr)) {}
543  Promise _pr;
544 };
545 
546 template <typename Promise, typename Func, typename... T>
547 struct continuation final : continuation_base_with_promise<Promise, T...> {
548  continuation(Promise&& pr, Func&& func, future_state<T...>&& state) : continuation_base_with_promise<Promise, T...>(std::move(pr), std::move(state)), _func(std::move(func)) {}
549  continuation(Promise&& pr, Func&& func) : continuation_base_with_promise<Promise, T...>(std::move(pr)), _func(std::move(func)) {}
550  virtual void run_and_dispose() noexcept override {
551  _func(this->_pr, std::move(this->_state));
552  delete this;
553  }
554  Func _func;
555 };
556 
557 namespace internal {
558 
559 template <typename... T>
560 future<T...> make_exception_future(future_state_base&& state) noexcept;
561 
562 template <typename... T, typename U>
563 void set_callback(future<T...>& fut, U* callback) noexcept;
564 
565 class future_base;
566 
567 class promise_base {
568 protected:
569  enum class urgent { no, yes };
570  future_base* _future = nullptr;
571 
572  // This points to the future_state that is currently being
573  // used. See comment above the future_state struct definition for
574  // details.
575  future_state_base* _state;
576 
577  task* _task = nullptr;
578 
579  promise_base(const promise_base&) = delete;
580  promise_base(future_state_base* state) noexcept : _state(state) {}
581  promise_base(future_base* future, future_state_base* state) noexcept;
582  void move_it(promise_base&& x) noexcept;
583  promise_base(promise_base&& x) noexcept;
584 
585  void clear() noexcept;
586 
587  // We never need to destruct this polymorphicly, so we can make it
588  // protected instead of virtual
589  ~promise_base() noexcept {
590  clear();
591  }
592 
593  void operator=(const promise_base&) = delete;
594  promise_base& operator=(promise_base&& x) noexcept;
595 
596  template<urgent Urgent>
597  void make_ready() noexcept;
598 
599  template<typename T>
600  void set_exception_impl(T&& val) noexcept {
601  if (_state) {
602  _state->set_exception(std::move(val));
603  make_ready<urgent::no>();
604  } else {
605  // We get here if promise::get_future is called and the
606  // returned future is destroyed without creating a
607  // continuation.
608  // In older versions of seastar we would store a local
609  // copy of ex and warn in the promise destructor.
610  // Since there isn't any way for the user to clear
611  // the exception, we issue the warning from here.
612  report_failed_future(val);
613  }
614  }
615 
616  void set_exception(future_state_base&& state) noexcept {
617  set_exception_impl(std::move(state));
618  }
619 
620  void set_exception(std::exception_ptr&& ex) noexcept {
621  set_exception_impl(std::move(ex));
622  }
623 
624  void set_exception(const std::exception_ptr& ex) noexcept {
625  set_exception(std::exception_ptr(ex));
626  }
627 
628  template<typename Exception>
629  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
630  set_exception(make_exception_ptr(std::forward<Exception>(e)));
631  }
632 
633  friend class future_base;
634  template <typename... U> friend class seastar::future;
635 
636 private:
637  void set_to_current_exception() noexcept;
638 };
639 
646 template <typename... T>
647 class promise_base_with_type : protected internal::promise_base {
648 protected:
649  future_state<T...>* get_state() {
650  return static_cast<future_state<T...>*>(_state);
651  }
652  static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
653 public:
654  promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
655  promise_base_with_type(future<T...>* future) noexcept : promise_base(future, &future->_state) { }
656  promise_base_with_type(promise_base_with_type&& x) noexcept = default;
657  promise_base_with_type(const promise_base_with_type&) = delete;
658  promise_base_with_type& operator=(promise_base_with_type&& x) noexcept = default;
659  void operator=(const promise_base_with_type&) = delete;
660 
661  void set_urgent_state(future_state<T...>&& state) noexcept {
662  auto* ptr = get_state();
663  // The state can be null if the corresponding future has been
664  // destroyed without producing a continuation.
665  if (ptr) {
666  // FIXME: This is a fairly expensive assert. It would be a
667  // good candidate for being disabled in release builds if
668  // we had such an assert.
669  assert(ptr->_u.st == future_state_base::state::future);
670  new (ptr) future_state<T...>(std::move(state));
671  make_ready<urgent::yes>();
672  }
673  }
674 
675  template <typename... A>
676  void set_value(A&&... a) {
677  if (auto *s = get_state()) {
678  s->set(std::forward<A>(a)...);
679  make_ready<urgent::no>();
680  }
681  }
682 
683 #if defined(SEASTAR_COROUTINES_TS) || defined(__cpp_lib_coroutine)
684  void set_coroutine(future_state<T...>& state, task& coroutine) noexcept {
685  _state = &state;
686  _task = &coroutine;
687  }
688 #endif
689 private:
690  template <typename Pr, typename Func>
691  void schedule(Pr&& pr, Func&& func) noexcept {
692  auto tws = new continuation<Pr, Func, T...>(std::move(pr), std::move(func));
693  _state = &tws->_state;
694  _task = tws;
695  }
696  void schedule(continuation_base<T...>* callback) noexcept {
697  _state = &callback->_state;
698  _task = callback;
699  }
700 
701  template <typename... U>
702  friend class seastar::future;
703 
704  friend struct seastar::future_state<T...>;
705 };
706 }
708 
714 template <typename... T>
715 class promise : private internal::promise_base_with_type<T...> {
716  future_state<T...> _local_state;
717 
718 public:
722  promise() noexcept : internal::promise_base_with_type<T...>(&_local_state) {}
723 
725  void move_it(promise&& x) noexcept;
726  promise(promise&& x) noexcept : internal::promise_base_with_type<T...>(std::move(x)) {
727  move_it(std::move(x));
728  }
729  promise(const promise&) = delete;
730  promise& operator=(promise&& x) noexcept {
731  internal::promise_base_with_type<T...>::operator=(std::move(x));
732  // If this is a self-move, _state is now nullptr and it is
733  // safe to call move_it.
734  move_it(std::move(x));
735  return *this;
736  }
737  void operator=(const promise&) = delete;
738 
745  future<T...> get_future() noexcept;
746 
758  template <typename... A>
759  void set_value(A&&... a) {
760  internal::promise_base_with_type<T...>::set_value(std::forward<A>(a)...);
761  }
762 
767  void set_exception(std::exception_ptr&& ex) noexcept {
768  internal::promise_base::set_exception(std::move(ex));
769  }
770 
771  void set_exception(const std::exception_ptr& ex) noexcept {
772  internal::promise_base::set_exception(ex);
773  }
774 
779  template<typename Exception>
780  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
781  internal::promise_base::set_exception(std::forward<Exception>(e));
782  }
783 
784  using internal::promise_base_with_type<T...>::set_urgent_state;
785 
786  template <typename... U>
787  friend class future;
788 };
789 
795 template<>
796 class promise<void> : public promise<> {};
797 
799 
802 
803 
809 template <typename... T> struct is_future : std::false_type {};
810 
813 template <typename... T> struct is_future<future<T...>> : std::true_type {};
814 
816 
817 
821 template <typename T>
822 struct futurize;
823 
824 SEASTAR_CONCEPT(
825 
826 template <typename T>
827 concept Future = is_future<T>::value;
828 
829 template <typename Func, typename... T>
830 concept CanInvoke = requires (Func f, T... args) {
831  f(std::forward<T>(args)...);
832 };
833 
834 // Deprecated alias
835 template <typename Func, typename... T>
836 concept CanApply = CanInvoke<Func, T...>;
837 
838 template <typename Func, typename Return, typename... T>
839 concept InvokeReturns = requires (Func f, T... args) {
840  { f(std::forward<T>(args)...) } -> std::same_as<Return>;
841 };
842 
843 // Deprecated alias
844 template <typename Func, typename Return, typename... T>
845 concept ApplyReturns = InvokeReturns<Func, Return, T...>;
846 
847 template <typename Func, typename... T>
848 concept InvokeReturnsAnyFuture = requires (Func f, T... args) {
849  requires is_future<decltype(f(std::forward<T>(args)...))>::value;
850 };
851 
852 // Deprecated alias
853 template <typename Func, typename... T>
854 concept ApplyReturnsAnyFuture = InvokeReturnsAnyFuture<Func, T...>;
855 
856 )
857 
858 template <typename T>
859 struct futurize {
861  using type = future<T>;
865  using value_type = std::tuple<T>;
866 
869  template<typename Func, typename... FuncArgs>
870  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
871 
874  template<typename Func, typename... FuncArgs>
875  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
876 
878  template<typename Func, typename... FuncArgs>
879  [[deprecated("Use invoke for varargs")]]
880  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
881 
883  static inline type convert(T&& value) { return make_ready_future<T>(std::move(value)); }
884  static inline type convert(type&& value) { return std::move(value); }
885 
887  static type from_tuple(value_type&& value);
889  static type from_tuple(const value_type& value);
890 
892  template <typename Arg>
893  static type make_exception_future(Arg&& arg) noexcept;
894 
895 private:
899  template<typename Func>
900  SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func> )
901  static void satisfy_with_result_of(internal::promise_base_with_type<T>&&, Func&& func);
902 
903  template <typename... U>
904  friend class future;
905 };
906 
908 template <>
909 struct futurize<void> {
910  using type = future<>;
911  using promise_type = promise<>;
912  using value_type = std::tuple<>;
913 
914  template<typename Func, typename... FuncArgs>
915  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
916 
917  template<typename Func, typename... FuncArgs>
918  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
919 
920  template<typename Func, typename... FuncArgs>
921  [[deprecated("Use invoke for varargs")]]
922  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
923 
924  static inline type from_tuple(value_type&& value);
925  static inline type from_tuple(const value_type& value);
926 
927  template <typename Arg>
928  static type make_exception_future(Arg&& arg) noexcept;
929 
930 private:
931  template<typename Func>
932  SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func> )
933  static void satisfy_with_result_of(internal::promise_base_with_type<>&&, Func&& func);
934 
935  template <typename... U>
936  friend class future;
937 };
938 
939 template <typename... Args>
940 struct futurize<future<Args...>> {
941  using type = future<Args...>;
942  using promise_type = promise<Args...>;
943  using value_type = std::tuple<Args...>;
944 
945  template<typename Func, typename... FuncArgs>
946  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
947 
948  template<typename Func, typename... FuncArgs>
949  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
950 
951  template<typename Func, typename... FuncArgs>
952  [[deprecated("Use invoke for varargs")]]
953  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
954 
955  static inline type from_tuple(value_type&& value);
956  static inline type from_tuple(const value_type& value);
957 
958  static inline type convert(Args&&... values) { return make_ready_future<Args...>(std::move(values)...); }
959  static inline type convert(type&& value) { return std::move(value); }
960 
961  template <typename Arg>
962  static type make_exception_future(Arg&& arg) noexcept;
963 
964 private:
965  template<typename Func>
966  SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func> )
967  static void satisfy_with_result_of(internal::promise_base_with_type<Args...>&&, Func&& func);
968 
969  template <typename... U>
970  friend class future;
971 };
973 
974 // Converts a type to a future type, if it isn't already.
975 template <typename T>
976 using futurize_t = typename futurize<T>::type;
977 
979 
980 template<typename Func, typename... Args>
981 auto futurize_invoke(Func&& func, Args&&... args) noexcept;
982 
983 template<typename Func, typename... Args>
984 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept;
985 
988 namespace internal {
989 class future_base {
990 protected:
991  promise_base* _promise;
992  future_base() noexcept : _promise(nullptr) {}
993  future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
994  _promise->_future = this;
995  _promise->_state = state;
996  }
997 
998  void move_it(future_base&& x, future_state_base* state) noexcept {
999  _promise = x._promise;
1000  if (auto* p = _promise) {
1001  x.detach_promise();
1002  p->_future = this;
1003  p->_state = state;
1004  }
1005  }
1006 
1007  future_base(future_base&& x, future_state_base* state) noexcept {
1008  move_it(std::move(x), state);
1009  }
1010 
1011  void clear() noexcept {
1012  if (_promise) {
1013  detach_promise();
1014  }
1015  }
1016 
1017  ~future_base() noexcept {
1018  clear();
1019  }
1020 
1021  promise_base* detach_promise() noexcept {
1022  _promise->_state = nullptr;
1023  _promise->_future = nullptr;
1024  return std::exchange(_promise, nullptr);
1025  }
1026 
1027  friend class promise_base;
1028 };
1029 
1030 template <bool IsVariadic>
1031 struct warn_variadic_future {
1032  // Non-varidic case, do nothing
1033  void check_deprecation() {}
1034 };
1035 
1036 
1037 // Note: placing the deprecated attribute on the class specialization has no effect.
1038 template <>
1039 struct warn_variadic_future<true> {
1040  // Variadic case, has deprecation attribute
1041  [[deprecated("Variadic future<> with more than one template parmeter is deprecated, replace with future<std::tuple<...>>")]]
1042  void check_deprecation() {}
1043 };
1044 
1045 }
1046 
1089 template <typename... T>
1090 class SEASTAR_NODISCARD future : private internal::future_base, internal::warn_variadic_future<(sizeof...(T) > 1)> {
1091  future_state<T...> _state;
1092  static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
1093 private:
1094  // This constructor creates a future that is not ready but has no
1095  // associated promise yet. The use case is to have a less flexible
1096  // but more efficient future/promise pair where we know that
1097  // promise::set_value cannot possibly be called without a matching
1098  // future and so that promise doesn't need to store a
1099  // future_state.
1100  future(future_for_get_promise_marker m) noexcept { }
1101 
1102  future(promise<T...>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
1103  template <typename... A>
1104  future(ready_future_marker m, A&&... a) noexcept : _state(m, std::forward<A>(a)...) { }
1105  future(exception_future_marker m, std::exception_ptr&& ex) noexcept : _state(m, std::move(ex)) { }
1106  future(exception_future_marker m, future_state_base&& state) noexcept : _state(m, std::move(state)) { }
1107  [[gnu::always_inline]]
1108  explicit future(future_state<T...>&& state) noexcept
1109  : _state(std::move(state)) {
1110  }
1111  internal::promise_base_with_type<T...> get_promise() noexcept {
1112  assert(!_promise);
1113  return internal::promise_base_with_type<T...>(this);
1114  }
1115  internal::promise_base_with_type<T...>* detach_promise() {
1116  return static_cast<internal::promise_base_with_type<T...>*>(future_base::detach_promise());
1117  }
1118  template <typename Pr, typename Func>
1119  void schedule(Pr&& pr, Func&& func) noexcept {
1120  if (_state.available() || !_promise) {
1121  if (__builtin_expect(!_state.available() && !_promise, false)) {
1122  _state.set_to_broken_promise();
1123  }
1124  ::seastar::schedule(new continuation<Pr, Func, T...>(std::move(pr), std::move(func), std::move(_state)));
1125  } else {
1126  assert(_promise);
1127  detach_promise()->schedule(std::move(pr), std::move(func));
1128  _state._u.st = future_state_base::state::invalid;
1129  }
1130  }
1131 
1132  [[gnu::always_inline]]
1133  future_state<T...>&& get_available_state_ref() noexcept {
1134  if (_promise) {
1135  detach_promise();
1136  }
1137  return std::move(_state);
1138  }
1139 
1140  [[gnu::noinline]]
1141  future<T...> rethrow_with_nested() noexcept {
1142  if (!failed()) {
1143  return current_exception_as_future<T...>();
1144  } else {
1145  //
1146  // Encapsulate the current exception into the
1147  // std::nested_exception because the current libstdc++
1148  // implementation has a bug requiring the value of a
1149  // std::throw_with_nested() parameter to be of a polymorphic
1150  // type.
1151  //
1152  std::nested_exception f_ex;
1153  try {
1154  get();
1155  } catch (...) {
1156  try {
1157  std::throw_with_nested(f_ex);
1158  } catch (...) {
1159  return current_exception_as_future<T...>();
1160  }
1161  }
1162  __builtin_unreachable();
1163  }
1164  }
1165 
1166  template<typename... U>
1167  friend class shared_future;
1168 public:
1170  using value_type = std::tuple<T...>;
1172  using promise_type = promise<T...>;
1174  [[gnu::always_inline]]
1175  future(future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1176  future(const future&) = delete;
1177  ~future() {
1178  this->check_deprecation();
1179  }
1180  future& operator=(future&& x) noexcept {
1181  clear();
1182  move_it(std::move(x), &_state);
1183  _state = std::move(x._state);
1184  return *this;
1185  }
1186  void operator=(const future&) = delete;
1196  [[gnu::always_inline]]
1197  std::tuple<T...>&& get() {
1198  if (!_state.available()) {
1199  do_wait();
1200  }
1201  return get_available_state_ref().take();
1202  }
1203 
1204  [[gnu::always_inline]]
1205  std::exception_ptr get_exception() noexcept {
1206  return get_available_state_ref().get_exception();
1207  }
1208 
1217  typename future_state<T...>::get0_return_type get0() {
1218  return future_state<T...>::get0(get());
1219  }
1220 
1226  void wait() noexcept {
1227  if (!_state.available()) {
1228  do_wait();
1229  }
1230  }
1231 private:
1232  class thread_wake_task final : public continuation_base<T...> {
1233  thread_context* _thread;
1234  future* _waiting_for;
1235  public:
1236  thread_wake_task(thread_context* thread, future* waiting_for)
1237  : _thread(thread), _waiting_for(waiting_for) {
1238  }
1239  virtual void run_and_dispose() noexcept override {
1240  _waiting_for->_state = std::move(this->_state);
1241  thread_impl::switch_in(_thread);
1242  // no need to delete, since this is always allocated on
1243  // _thread's stack.
1244  }
1245  };
1246  void do_wait() noexcept {
1247  if (__builtin_expect(!_promise, false)) {
1248  _state.set_to_broken_promise();
1249  return;
1250  }
1251  auto thread = thread_impl::get();
1252  assert(thread);
1253  thread_wake_task wake_task{thread, this};
1254  detach_promise()->schedule(static_cast<continuation_base<T...>*>(&wake_task));
1255  thread_impl::switch_out(thread);
1256  }
1257 
1258 public:
1262  [[gnu::always_inline]]
1263  bool available() const noexcept {
1264  return _state.available();
1265  }
1266 
1270  [[gnu::always_inline]]
1271  bool failed() const noexcept {
1272  return _state.failed();
1273  }
1274 
1290  template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1291  SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func, T...> )
1292  Result
1293  then(Func&& func) noexcept {
1294 #ifndef SEASTAR_TYPE_ERASE_MORE
1295  return then_impl(std::move(func));
1296 #else
1297  return then_impl(noncopyable_function<Result (T&&...)>([func = std::forward<Func>(func)] (T&&... args) mutable {
1298  return futurize_invoke(func, std::forward<decltype(args)>(args)...);
1299  }));
1300 #endif
1301  }
1302 
1303 private:
1304 
1305  // Keep this simple so that Named Return Value Optimization is used.
1306  template <typename Func, typename Result>
1307  Result then_impl_nrvo(Func&& func) noexcept {
1308  using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1309  typename futurator::type fut(future_for_get_promise_marker{});
1310  // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1311  // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1312  // that happens.
1313  [&] () noexcept {
1314  using pr_type = decltype(fut.get_promise());
1315  memory::disable_failure_guard dfg;
1316  schedule(fut.get_promise(), [func = std::forward<Func>(func)] (pr_type& pr, future_state<T...>&& state) mutable {
1317  if (state.failed()) {
1318  pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1319  } else {
1320  try {
1321  futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1322  return ::seastar::apply(std::forward<Func>(func), std::move(state).get_value());
1323  });
1324  } catch (...) {
1325  pr.set_to_current_exception();
1326  }
1327  }
1328  });
1329  } ();
1330  return fut;
1331  }
1332 
1333  template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1334  Result
1335  then_impl(Func&& func) noexcept {
1336  using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1337  if (available() && !need_preempt()) {
1338  if (failed()) {
1339  return futurator::make_exception_future(static_cast<future_state_base&&>(get_available_state_ref()));
1340  } else {
1341  return futurator::apply(std::forward<Func>(func), get_available_state_ref().take_value());
1342  }
1343  }
1344  return then_impl_nrvo<Func, Result>(std::forward<Func>(func));
1345  }
1346 
1347 public:
1363  template <typename Func, typename FuncResult = std::result_of_t<Func(future)>>
1364  SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func, future> )
1365  futurize_t<FuncResult>
1366  then_wrapped(Func&& func) & noexcept {
1367  return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1368  }
1369 
1370  template <typename Func, typename FuncResult = std::result_of_t<Func(future&&)>>
1371  SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func, future&&> )
1372  futurize_t<FuncResult>
1373  then_wrapped(Func&& func) && noexcept {
1374  return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1375  }
1376 
1377 private:
1378 
1379  template <bool AsSelf, typename FuncResult, typename Func>
1380  futurize_t<FuncResult>
1381  then_wrapped_maybe_erase(Func&& func) noexcept {
1382 #ifndef SEASTAR_TYPE_ERASE_MORE
1383  return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1384 #else
1385  using futurator = futurize<FuncResult>;
1386  using WrapFuncResult = typename futurator::type;
1387  return then_wrapped_common<AsSelf, WrapFuncResult>(noncopyable_function<WrapFuncResult (future&&)>([func = std::forward<Func>(func)] (future&& f) mutable {
1388  return futurator::invoke(std::forward<Func>(func), std::move(f));
1389  }));
1390 #endif
1391  }
1392 
1393  // Keep this simple so that Named Return Value Optimization is used.
1394  template <typename FuncResult, typename Func>
1395  futurize_t<FuncResult>
1396  then_wrapped_nrvo(Func&& func) noexcept {
1397  using futurator = futurize<FuncResult>;
1398  typename futurator::type fut(future_for_get_promise_marker{});
1399  // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1400  // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1401  // that happens.
1402  [&] () noexcept {
1403  using pr_type = decltype(fut.get_promise());
1404  memory::disable_failure_guard dfg;
1405  schedule(fut.get_promise(), [func = std::forward<Func>(func)] (pr_type& pr, future_state<T...>&& state) mutable {
1406  try {
1407  futurator::satisfy_with_result_of(std::move(pr), [&func, &state] {
1408  return func(future(std::move(state)));
1409  });
1410  } catch (...) {
1411  pr.set_to_current_exception();
1412  }
1413  });
1414  } ();
1415  return fut;
1416  }
1417 
1418 
1419  template <bool AsSelf, typename FuncResult, typename Func>
1420  futurize_t<FuncResult>
1421  then_wrapped_common(Func&& func) noexcept {
1422  using futurator = futurize<FuncResult>;
1423  if (available() && !need_preempt()) {
1424  // TODO: after dropping C++14 support use `if constexpr ()` instead.
1425  if (AsSelf) {
1426  if (_promise) {
1427  detach_promise();
1428  }
1429  return futurator::invoke(std::forward<Func>(func), std::move(*this));
1430  } else {
1431  return futurator::invoke(std::forward<Func>(func), future(get_available_state_ref()));
1432  }
1433  }
1434  return then_wrapped_nrvo<FuncResult, Func>(std::forward<Func>(func));
1435  }
1436 
1437  void forward_to(internal::promise_base_with_type<T...>&& pr) noexcept {
1438  if (_state.available()) {
1439  pr.set_urgent_state(std::move(_state));
1440  } else {
1441  *detach_promise() = std::move(pr);
1442  }
1443  }
1444 
1445 public:
1456  void forward_to(promise<T...>&& pr) noexcept {
1457  if (_state.available()) {
1458  pr.set_urgent_state(std::move(_state));
1459  } else if (&pr._local_state != pr._state) {
1460  // The only case when _state points to _local_state is
1461  // when get_future was never called. Given that pr will
1462  // soon be destroyed, we know get_future will never be
1463  // called and we can just ignore this request.
1464  *detach_promise() = std::move(pr);
1465  }
1466  }
1467 
1468 
1469 
1485  template <typename Func>
1486  SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func> )
1487  future<T...> finally(Func&& func) noexcept {
1488  return then_wrapped(finally_body<Func, is_future<std::result_of_t<Func()>>::value>(std::forward<Func>(func)));
1489  }
1490 
1491 
1492  template <typename Func, bool FuncReturnsFuture>
1494 
1495  template <typename Func>
1496  struct finally_body<Func, true> {
1497  Func _func;
1498 
1499  finally_body(Func&& func) : _func(std::forward<Func>(func))
1500  { }
1501 
1502  future<T...> operator()(future<T...>&& result) noexcept {
1503  return futurize_invoke(_func).then_wrapped([result = std::move(result)](auto&& f_res) mutable {
1504  if (!f_res.failed()) {
1505  return std::move(result);
1506  } else {
1507  try {
1508  f_res.get();
1509  } catch (...) {
1510  return result.rethrow_with_nested();
1511  }
1512  __builtin_unreachable();
1513  }
1514  });
1515  }
1516  };
1517 
1518  template <typename Func>
1519  struct finally_body<Func, false> {
1520  Func _func;
1521 
1522  finally_body(Func&& func) : _func(std::forward<Func>(func))
1523  { }
1524 
1525  future<T...> operator()(future<T...>&& result) noexcept {
1526  try {
1527  _func();
1528  return std::move(result);
1529  } catch (...) {
1530  return result.rethrow_with_nested();
1531  }
1532  };
1533  };
1534 
1539  future<> or_terminate() noexcept {
1540  return then_wrapped([] (auto&& f) {
1541  try {
1542  f.get();
1543  } catch (...) {
1544  engine_exit(std::current_exception());
1545  }
1546  });
1547  }
1548 
1554  return then([] (T&&...) {});
1555  }
1556 
1570  template <typename Func>
1571  /* Broken?
1572  SEASTAR_CONCEPT( requires ::seastar::InvokeReturns<Func, future<T...>, std::exception_ptr>
1573  || (sizeof...(T) == 0 && ::seastar::InvokeReturns<Func, void, std::exception_ptr>)
1574  || (sizeof...(T) == 1 && ::seastar::InvokeReturns<Func, T..., std::exception_ptr>)
1575  ) */
1576  future<T...> handle_exception(Func&& func) noexcept {
1577  return then_wrapped([func = std::forward<Func>(func)]
1578  (auto&& fut) mutable -> future<T...> {
1579  if (!fut.failed()) {
1580  return make_ready_future<T...>(fut.get());
1581  } else {
1582  return futurize_invoke(func, fut.get_exception());
1583  }
1584  });
1585  }
1586 
1597  template <typename Func>
1598  future<T...> handle_exception_type(Func&& func) noexcept {
1599  using trait = function_traits<Func>;
1600  static_assert(trait::arity == 1, "func can take only one parameter");
1601  using ex_type = typename trait::template arg<0>::type;
1602  return then_wrapped([func = std::forward<Func>(func)]
1603  (auto&& fut) mutable -> future<T...> {
1604  try {
1605  return make_ready_future<T...>(fut.get());
1606  } catch(ex_type& ex) {
1607  return futurize_invoke(func, ex);
1608  }
1609  });
1610  }
1611 
1617  void ignore_ready_future() noexcept {
1618  _state.ignore();
1619  }
1620 
1621 #if defined(SEASTAR_COROUTINES_TS) || defined(__cpp_lib_coroutine)
1622  void set_coroutine(task& coroutine) noexcept {
1623  assert(!_state.available());
1624  assert(_promise);
1625  detach_promise()->set_coroutine(_state, coroutine);
1626  }
1627 #endif
1628 private:
1629  void set_callback(continuation_base<T...>* callback) noexcept {
1630  if (_state.available()) {
1631  callback->set_state(get_available_state_ref());
1632  ::seastar::schedule(callback);
1633  } else {
1634  assert(_promise);
1635  detach_promise()->schedule(callback);
1636  }
1637 
1638  }
1639 
1641  template <typename... U>
1642  friend class future;
1643  template <typename... U>
1644  friend class promise;
1645  template <typename U>
1646  friend struct futurize;
1647  template <typename... U>
1648  friend class internal::promise_base_with_type;
1649  template <typename... U, typename... A>
1650  friend future<U...> make_ready_future(A&&... value) noexcept;
1651  template <typename... U>
1652  friend future<U...> make_exception_future(std::exception_ptr&& ex) noexcept;
1653  template <typename... U, typename Exception>
1654  friend future<U...> make_exception_future(Exception&& ex) noexcept;
1655  template <typename... U>
1656  friend future<U...> internal::make_exception_future(future_state_base&& state) noexcept;
1657  template <typename... U, typename V>
1658  friend void internal::set_callback(future<U...>&, V*) noexcept;
1660 };
1661 
1662 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1663  : _future(future), _state(state) {
1664  _future->_promise = this;
1665 }
1666 
1667 template <typename... T>
1668 inline
1669 future<T...>
1671  assert(!this->_future && this->_state && !this->_task);
1672  return future<T...>(this);
1673 }
1674 
1675 template <typename... T>
1676 inline
1677 void promise<T...>::move_it(promise&& x) noexcept {
1678  if (this->_state == &x._local_state) {
1679  this->_state = &_local_state;
1680  new (&_local_state) future_state<T...>(std::move(x._local_state));
1681  }
1682 }
1683 
1684 template <typename... T, typename... A>
1685 inline
1686 future<T...> make_ready_future(A&&... value) noexcept {
1687  return future<T...>(ready_future_marker(), std::forward<A>(value)...);
1688 }
1689 
1690 template <typename... T>
1691 inline
1692 future<T...> make_exception_future(std::exception_ptr&& ex) noexcept {
1693  return future<T...>(exception_future_marker(), std::move(ex));
1694 }
1695 
1696 template <typename... T>
1697 inline
1698 future<T...> internal::make_exception_future(future_state_base&& state) noexcept {
1699  return future<T...>(exception_future_marker(), std::move(state));
1700 }
1701 
1702 template <typename... T>
1704  return internal::make_exception_future<T...>(future_state_base::current_exception());
1705 }
1706 
1707 void log_exception_trace() noexcept;
1708 
1715 template <typename... T, typename Exception>
1716 inline
1717 future<T...> make_exception_future(Exception&& ex) noexcept {
1718  log_exception_trace();
1719  return make_exception_future<T...>(std::make_exception_ptr(std::forward<Exception>(ex)));
1720 }
1721 
1723 
1725 
1726 template<typename T>
1727 template<typename Func, typename... FuncArgs>
1728 typename futurize<T>::type futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1729  try {
1730  return convert(::seastar::apply(std::forward<Func>(func), std::move(args)));
1731  } catch (...) {
1732  return current_exception_as_future<T>();
1733  }
1734 }
1735 
1736 template<typename T>
1737 template<typename Func>
1738 SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func> )
1739 void futurize<T>::satisfy_with_result_of(internal::promise_base_with_type<T>&& pr, Func&& func) {
1740  pr.set_value(func());
1741 }
1742 
1743 template<typename T>
1744 template<typename Func, typename... FuncArgs>
1745 typename futurize<T>::type futurize<T>::invoke(Func&& func, FuncArgs&&... args) noexcept {
1746  try {
1747  return convert(func(std::forward<FuncArgs>(args)...));
1748  } catch (...) {
1749  return current_exception_as_future<T>();
1750  }
1751 }
1752 
1753 template<typename T>
1754 template<typename Func, typename... FuncArgs>
1755 typename futurize<T>::type futurize<T>::apply(Func&& func, FuncArgs&&... args) noexcept {
1756  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1757 }
1758 
1759 template<typename Func, typename... FuncArgs>
1760 typename futurize<void>::type futurize<void>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1761  try {
1762  ::seastar::apply(std::forward<Func>(func), std::move(args));
1763  return make_ready_future<>();
1764  } catch (...) {
1765  return current_exception_as_future<>();
1766  }
1767 }
1768 
1769 template<typename Func>
1770 SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func> )
1771  void futurize<void>::satisfy_with_result_of(internal::promise_base_with_type<>&& pr, Func&& func) {
1772  func();
1773  pr.set_value();
1774 }
1775 
1776 template<typename Func, typename... FuncArgs>
1777 typename futurize<void>::type futurize<void>::invoke(Func&& func, FuncArgs&&... args) noexcept {
1778  try {
1779  func(std::forward<FuncArgs>(args)...);
1780  return make_ready_future<>();
1781  } catch (...) {
1782  return current_exception_as_future<>();
1783  }
1784 }
1785 
1786 template<typename Func, typename... FuncArgs>
1787 typename futurize<void>::type futurize<void>::apply(Func&& func, FuncArgs&&... args) noexcept {
1788  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1789 }
1790 
1791 template<typename... Args>
1792 template<typename Func, typename... FuncArgs>
1793 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1794  try {
1795  return ::seastar::apply(std::forward<Func>(func), std::move(args));
1796  } catch (...) {
1797  return current_exception_as_future<Args...>();
1798  }
1799 }
1800 
1801 template<typename... Args>
1802 template<typename Func>
1803 SEASTAR_CONCEPT( requires ::seastar::CanInvoke<Func> )
1804 void futurize<future<Args...>>::satisfy_with_result_of(internal::promise_base_with_type<Args...>&& pr, Func&& func) {
1805  func().forward_to(std::move(pr));
1806 }
1807 
1808 template<typename... Args>
1809 template<typename Func, typename... FuncArgs>
1810 typename futurize<future<Args...>>::type futurize<future<Args...>>::invoke(Func&& func, FuncArgs&&... args) noexcept {
1811  try {
1812  return func(std::forward<FuncArgs>(args)...);
1813  } catch (...) {
1814  return current_exception_as_future<Args...>();
1815  }
1816 }
1817 
1818 template<typename... Args>
1819 template<typename Func, typename... FuncArgs>
1820 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, FuncArgs&&... args) noexcept {
1821  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1822 }
1823 
1824 template <typename T>
1825 template <typename Arg>
1826 inline
1827 future<T>
1828 futurize<T>::make_exception_future(Arg&& arg) noexcept {
1831  return make_exception_future<T>(std::forward<Arg>(arg));
1832 }
1833 
1834 template <typename... T>
1835 template <typename Arg>
1836 inline
1837 future<T...>
1838 futurize<future<T...>>::make_exception_future(Arg&& arg) noexcept {
1841  return make_exception_future<T...>(std::forward<Arg>(arg));
1842 }
1843 
1844 template <typename Arg>
1845 inline
1846 future<>
1847 futurize<void>::make_exception_future(Arg&& arg) noexcept {
1850  return make_exception_future<>(std::forward<Arg>(arg));
1851 }
1852 
1853 template <typename T>
1854 inline
1855 future<T>
1856 futurize<T>::from_tuple(std::tuple<T>&& value) {
1857  return make_ready_future<T>(std::move(value));
1858 }
1859 
1860 template <typename T>
1861 inline
1862 future<T>
1863 futurize<T>::from_tuple(const std::tuple<T>& value) {
1864  return make_ready_future<T>(value);
1865 }
1866 
1867 inline
1868 future<>
1869 futurize<void>::from_tuple(std::tuple<>&& value) {
1870  return make_ready_future<>();
1871 }
1872 
1873 inline
1874 future<>
1875 futurize<void>::from_tuple(const std::tuple<>& value) {
1876  return make_ready_future<>();
1877 }
1878 
1879 template <typename... Args>
1880 inline
1881 future<Args...>
1882 futurize<future<Args...>>::from_tuple(std::tuple<Args...>&& value) {
1883  return make_ready_future<Args...>(std::move(value));
1884 }
1885 
1886 template <typename... Args>
1887 inline
1888 future<Args...>
1889 futurize<future<Args...>>::from_tuple(const std::tuple<Args...>& value) {
1890  return make_ready_future<Args...>(value);
1891 }
1892 
1893 template<typename Func, typename... Args>
1894 auto futurize_invoke(Func&& func, Args&&... args) noexcept {
1895  using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
1896  return futurator::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
1897 }
1898 
1899 template<typename Func, typename... Args>
1900 [[deprecated("Use futurize_invoke for varargs")]]
1901 auto futurize_apply(Func&& func, Args&&... args) noexcept {
1902  return futurize_invoke(std::forward<Func>(func), std::forward<Args>(args)...);
1903 }
1904 
1905 template<typename Func, typename... Args>
1906 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) noexcept {
1907  using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
1908  return futurator::apply(std::forward<Func>(func), std::move(args));
1909 }
1910 
1911 namespace internal {
1912 
1913 template <typename... T, typename U>
1914 inline
1915 void set_callback(future<T...>& fut, U* callback) noexcept {
1916  // It would be better to use continuation_base<T...> for U, but
1917  // then a derived class of continuation_base<T...> won't be matched
1918  return fut.set_callback(callback);
1919 }
1920 
1921 }
1922 
1923 
1925 
1926 }
future< T... > handle_exception_type(Func &&func) noexcept
Handle the exception of a certain type carried by this future.
Definition: future.hh:1598
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:1366
Definition: noncopyable_function.hh:33
Definition: future.hh:408
A representation of a possibly not-yet-computed value.
Definition: future.hh:83
future< T... > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1692
void wait() noexcept
Definition: future.hh:1226
static type make_exception_future(Arg &&arg) noexcept
Makes an exceptional future of type type.
void set_exception(std::exception_ptr &&ex) noexcept
Marks the promise as failed.
Definition: future.hh:767
promise() noexcept
Constructs an empty promise.
Definition: future.hh:722
Definition: future.hh:288
Check whether a type is a future.
Definition: future.hh:809
bool failed() const noexcept
Checks whether the future has failed.
Definition: future.hh:1271
STL namespace.
static type apply(Func &&func, std::tuple< FuncArgs... > &&args) noexcept
thread - stateful thread of execution
Definition: thread.hh:143
Exception type for broken promises.
Definition: future.hh:133
future< T... > make_ready_future(A &&... value) noexcept
Creates a future in an available, value state.
Definition: future.hh:1686
static type from_tuple(value_type &&value)
Convert the tuple representation into a future.
Converts a type to a future type, if it isn&#39;t already.
Definition: future.hh:822
void move_it(promise &&x) noexcept
Moves a promise object.
Definition: future.hh:1677
void forward_to(promise< T... > &&pr) noexcept
Satisfy some promise object with this future as a result.
Definition: future.hh:1456
promise - allows a future value to be made available at a later time.
Definition: future.hh:80
std::tuple< T > value_type
The value tuple type associated with type.
Definition: future.hh:865
bool available() const noexcept
Checks whether the future is available.
Definition: future.hh:1263
future< T... > handle_exception(Func &&func) noexcept
Handle the exception carried by this future.
Definition: future.hh:1576
future_state< T... >::get0_return_type get0()
Definition: future.hh:1217
Definition: future.hh:1493
static type invoke(Func &&func, FuncArgs &&... args) noexcept
static type convert(T &&value)
Convert a value or a future to a future.
Definition: future.hh:883
Definition: function_traits.hh:29
Result then(Func &&func) noexcept
Schedule a block of code to run when the future is ready.
Definition: future.hh:1293
future< T > type
If T is a future, T; otherwise future<T>
Definition: future.hh:861
Definition: future.hh:272
future< T... > get_future() noexcept
Gets the promise&#39;s associated future.
Definition: future.hh:1670
friend future< U... > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:1703
Definition: task.hh:29
Definition: future.hh:409
future< T... > make_exception_future(Exception &&ex) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1717
future(future &&x) noexcept
Moves the future into a new object.
Definition: future.hh:1175
std::tuple< T... > value_type
The data type carried by the future.
Definition: future.hh:1170
future< T... > current_exception_as_future() noexcept
Returns std::current_exception() wrapped in a future.
Definition: future.hh:1703
Like future except the result can be waited for by many fibers.
Definition: future.hh:86
future or_terminate() noexcept
Terminate the program if this future fails.
Definition: future.hh:1539
future discard_result() noexcept
Discards the value carried by this future.
Definition: future.hh:1553
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:780
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
void ignore_ready_future() noexcept
Ignore any result hold by this future.
Definition: future.hh:1617