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/gcc6-concepts.hh>
38 #include <seastar/util/noncopyable_function.hh>
39 
40 namespace seastar {
41 
65 
70 
71 
74 
75 template <class... T>
76 class promise;
77 
78 template <class... T>
79 class future;
80 
81 template <typename... T>
83 
84 struct future_state_base;
85 
92 template <typename... T, typename... A>
93 future<T...> make_ready_future(A&&... value);
94 
101 template <typename... T>
102 future<T...> make_exception_future(std::exception_ptr&& value) noexcept;
103 
104 template <typename... T>
105 future<T...> make_exception_future(const std::exception_ptr& ex) noexcept {
106  return make_exception_future<T...>(std::exception_ptr(ex));
107 }
108 
109 template <typename... T>
110 future<T...> make_exception_future(std::exception_ptr& ex) noexcept {
111  return make_exception_future<T...>(static_cast<const std::exception_ptr&>(ex));
112 }
113 
115 void engine_exit(std::exception_ptr eptr = {});
116 
117 void report_failed_future(const std::exception_ptr& ex) noexcept;
118 
119 void report_failed_future(const future_state_base& state) noexcept;
120 
122 
129 struct broken_promise : std::logic_error {
130  broken_promise();
131 };
132 
133 namespace internal {
134 template <class... T>
135 class promise_base_with_type;
136 
137 template <typename... T>
138 future<T...> current_exception_as_future() noexcept;
139 
140 extern template
141 future<> current_exception_as_future() noexcept;
142 
143 // 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
144 // fails the build even if it is in the non enabled side of std::conditional.
145 template <typename... T>
146 struct get0_return_type {
147  using type = void;
148  static type get0(std::tuple<T...> v) { }
149 };
150 
151 template <typename T0, typename... T>
152 struct get0_return_type<T0, T...> {
153  using type = T0;
154  static type get0(std::tuple<T0, T...> v) { return std::get<0>(std::move(v)); }
155 };
156 
164 template <typename T, bool is_trivial_class>
165 struct uninitialized_wrapper_base;
166 
167 template <typename T>
168 struct uninitialized_wrapper_base<T, false> {
169  union any {
170  any() {}
171  ~any() {}
172  T value;
173  } _v;
174 
175 public:
176  template<typename... U>
177  void uninitialized_set(U&&... vs) {
178  new (&_v.value) T(std::forward<U>(vs)...);
179  }
180  T& uninitialized_get() {
181  return _v.value;
182  }
183  const T& uninitialized_get() const {
184  return _v.value;
185  }
186 };
187 
188 template <typename T> struct uninitialized_wrapper_base<T, true> : private T {
189  template<typename... U>
190  void uninitialized_set(U&&... vs) {
191  new (this) T(std::forward<U>(vs)...);
192  }
193  T& uninitialized_get() {
194  return *this;
195  }
196  const T& uninitialized_get() const {
197  return *this;
198  }
199 };
200 
201 template <typename T>
202 constexpr bool can_inherit =
203 #ifdef _LIBCPP_VERSION
204 // We expect std::tuple<> to be trivially constructible and
205 // destructible. That is not the case with libc++
206 // (https://bugs.llvm.org/show_bug.cgi?id=41714). We could avoid this
207 // optimization when using libc++ and relax the asserts, but
208 // inspection suggests that std::tuple<> is trivial, it is just not
209 // marked as such.
210  std::is_same<std::tuple<>, T>::value ||
211 #endif
212  (std::is_trivially_destructible<T>::value && std::is_trivially_constructible<T>::value &&
213  std::is_class<T>::value && !std::is_final<T>::value);
214 
215 // The objective is to avoid extra space for empty types like std::tuple<>. We could use std::is_empty_v, but it is
216 // better to check that both the constructor and destructor can be skipped.
217 template <typename T>
218 struct uninitialized_wrapper
219  : public uninitialized_wrapper_base<T, can_inherit<T>> {};
220 
221 static_assert(std::is_empty<uninitialized_wrapper<std::tuple<>>>::value, "This should still be empty");
222 
223 template <typename T>
224 struct is_trivially_move_constructible_and_destructible {
225  static constexpr bool value = std::is_trivially_move_constructible<T>::value && std::is_trivially_destructible<T>::value;
226 };
227 
228 template <bool... v>
229 struct all_true : std::false_type {};
230 
231 template <>
232 struct all_true<> : std::true_type {};
233 
234 template <bool... v>
235 struct all_true<true, v...> : public all_true<v...> {};
236 }
237 
238 //
239 // A future/promise pair maintain one logical value (a future_state).
240 // There are up to three places that can store it, but only one is
241 // active at any time.
242 //
243 // - in the promise _local_state member variable
244 //
245 // This is necessary because a promise is created first and there
246 // would be nowhere else to put the value.
247 //
248 // - in the future _state variable
249 //
250 // This is used anytime a future exists and then has not been called
251 // yet. This guarantees a simple access to the value for any code
252 // that already has a future.
253 //
254 // - in the task associated with the .then() clause (after .then() is called,
255 // if a value was not set)
256 //
257 //
258 // The promise maintains a pointer to the state, which is modified as
259 // the state moves to a new location due to events (such as .then() or
260 // get_future being called) or due to the promise or future being
261 // moved around.
262 //
263 
264 // non templated base class to reduce code duplication
266  static_assert(std::is_nothrow_copy_constructible<std::exception_ptr>::value,
267  "std::exception_ptr's copy constructor must not throw");
268  static_assert(std::is_nothrow_move_constructible<std::exception_ptr>::value,
269  "std::exception_ptr's move constructor must not throw");
270  static_assert(sizeof(std::exception_ptr) == sizeof(void*), "exception_ptr not a pointer");
271  enum class state : uintptr_t {
272  invalid = 0,
273  future = 1,
274  // the substate is intended to decouple the run-time prevention
275  // for duplicative result extraction (calling e.g. then() twice
276  // ends up in abandoned()) from the wrapped object's destruction
277  // handling which is orchestrated by future_state. Instead of
278  // creating a temporary future_state just for the sake of setting
279  // the "invalid" in the source instance, result_unavailable can
280  // be set to ensure future_state_base::available() returns false.
281  result_unavailable = 2,
282  result = 3,
283  exception_min = 4, // or anything greater
284  };
285  union any {
286  any() { st = state::future; }
287  any(state s) { st = s; }
288  void set_exception(std::exception_ptr&& e) {
289  new (&ex) std::exception_ptr(std::move(e));
290  assert(st >= state::exception_min);
291  }
292  any(std::exception_ptr&& e) {
293  set_exception(std::move(e));
294  }
295  ~any() {}
296  std::exception_ptr take_exception() {
297  std::exception_ptr ret(std::move(ex));
298  // Unfortunately in libstdc++ ~exception_ptr is defined out of line. We know that it does nothing for
299  // moved out values, so we omit calling it. This is critical for the code quality produced for this
300  // function. Without the out of line call, gcc can figure out that both sides of the if produce
301  // identical code and merges them.if
302  // We don't make any assumptions about other c++ libraries.
303  // There is request with gcc to define it inline: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90295
304 #ifndef __GLIBCXX__
305  ex.~exception_ptr();
306 #endif
307  st = state::invalid;
308  return ret;
309  }
310  any(any&& x) {
311  if (x.st < state::exception_min) {
312  st = x.st;
313  x.st = state::invalid;
314  } else {
315  new (&ex) std::exception_ptr(x.take_exception());
316  }
317  }
318  bool has_result() const {
319  return st == state::result || st == state::result_unavailable;
320  }
321  state st;
322  std::exception_ptr ex;
323  } _u;
324 
325  future_state_base() noexcept { }
326  future_state_base(state st) noexcept : _u(st) { }
327  future_state_base(std::exception_ptr&& ex) noexcept : _u(std::move(ex)) { }
328  future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
329 
330  // We never need to destruct this polymorphicly, so we can make it
331  // protected instead of virtual.
332 protected:
333  ~future_state_base() noexcept {
334  if (failed()) {
335  report_failed_future(_u.take_exception());
336  }
337  }
338 
339 public:
340 
341  bool valid() const noexcept { return _u.st != state::invalid; }
342  bool available() const noexcept { return _u.st == state::result || _u.st >= state::exception_min; }
343  bool failed() const noexcept { return __builtin_expect(_u.st >= state::exception_min, false); }
344 
345  void set_to_broken_promise() noexcept;
346 
347  void ignore() noexcept;
348 
349  void set_exception(std::exception_ptr&& ex) noexcept {
350  assert(_u.st == state::future);
351  _u.set_exception(std::move(ex));
352  }
353  future_state_base& operator=(future_state_base&& x) noexcept {
354  this->~future_state_base();
355  new (this) future_state_base(std::move(x));
356  return *this;
357  }
358  void set_exception(future_state_base&& state) noexcept {
359  assert(_u.st == state::future);
360  *this = std::move(state);
361  }
362  std::exception_ptr get_exception() && noexcept {
363  assert(_u.st >= state::exception_min);
364  // Move ex out so future::~future() knows we've handled it
365  return _u.take_exception();
366  }
367  const std::exception_ptr& get_exception() const& noexcept {
368  assert(_u.st >= state::exception_min);
369  return _u.ex;
370  }
371 
372  static future_state_base current_exception();
373 
374  template <typename... U>
375  friend future<U...> internal::current_exception_as_future() noexcept;
376 };
377 
381 
383 template <typename... T>
384 struct future_state : public future_state_base, private internal::uninitialized_wrapper<std::tuple<T...>> {
385  static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible<std::tuple<T...>>::value;
386  static constexpr bool has_trivial_move_and_destroy =
387  internal::all_true<internal::is_trivially_move_constructible_and_destructible<T>::value...>::value;
388  static_assert(std::is_nothrow_move_constructible<std::tuple<T...>>::value,
389  "Types must be no-throw move constructible");
390  static_assert(std::is_nothrow_destructible<std::tuple<T...>>::value,
391  "Types must be no-throw destructible");
392  future_state() noexcept {}
393  [[gnu::always_inline]]
394  future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
395  if (has_trivial_move_and_destroy) {
396 #pragma GCC diagnostic push
397 // Unfortunately gcc 8 warns about the memcpy of uninitialized
398 // memory. We can drop this when we drop support for gcc 8.
399 #pragma GCC diagnostic ignored "-Wuninitialized"
400  memcpy(reinterpret_cast<char*>(&this->uninitialized_get()),
401  &x.uninitialized_get(),
402  internal::used_size<std::tuple<T...>>::value);
403 #pragma GCC diagnostic pop
404  } else if (_u.has_result()) {
405  this->uninitialized_set(std::move(x.uninitialized_get()));
406  x.uninitialized_get().~tuple();
407  }
408  }
409  __attribute__((always_inline))
410  ~future_state() noexcept {
411  if (_u.has_result()) {
412  this->uninitialized_get().~tuple();
413  }
414  }
415  future_state& operator=(future_state&& x) noexcept {
416  this->~future_state();
417  new (this) future_state(std::move(x));
418  return *this;
419  }
420  template <typename... A>
421  future_state(ready_future_marker, A&&... a) : future_state_base(state::result) {
422  this->uninitialized_set(std::forward<A>(a)...);
423  }
424  template <typename... A>
425  void set(A&&... a) {
426  assert(_u.st == state::future);
427  new (this) future_state(ready_future_marker(), std::forward<A>(a)...);
428  }
429  future_state(exception_future_marker m, std::exception_ptr&& ex) : future_state_base(std::move(ex)) { }
430  future_state(exception_future_marker m, future_state_base&& state) : future_state_base(std::move(state)) { }
431  std::tuple<T...>&& get_value() && noexcept {
432  assert(_u.st == state::result);
433  return std::move(this->uninitialized_get());
434  }
435  std::tuple<T...>&& take_value() && noexcept {
436  assert(_u.st == state::result);
437  _u.st = state::result_unavailable;
438  return std::move(this->uninitialized_get());
439  }
440  template<typename U = std::tuple<T...>>
441  const std::enable_if_t<std::is_copy_constructible<U>::value, U>& get_value() const& noexcept(copy_noexcept) {
442  assert(_u.st == state::result);
443  return this->uninitialized_get();
444  }
445  std::tuple<T...>&& take() && {
446  assert(available());
447  if (_u.st >= state::exception_min) {
448  // Move ex out so future::~future() knows we've handled it
449  std::rethrow_exception(std::move(*this).get_exception());
450  }
451  _u.st = state::result_unavailable;
452  return std::move(this->uninitialized_get());
453  }
454  std::tuple<T...>&& get() && {
455  assert(available());
456  if (_u.st >= state::exception_min) {
457  // Move ex out so future::~future() knows we've handled it
458  std::rethrow_exception(std::move(*this).get_exception());
459  }
460  return std::move(this->uninitialized_get());
461  }
462  const std::tuple<T...>& get() const& {
463  assert(available());
464  if (_u.st >= state::exception_min) {
465  std::rethrow_exception(_u.ex);
466  }
467  return this->uninitialized_get();
468  }
469  using get0_return_type = typename internal::get0_return_type<T...>::type;
470  static get0_return_type get0(std::tuple<T...>&& x) {
471  return internal::get0_return_type<T...>::get0(std::move(x));
472  }
473 };
474 
475 static_assert(sizeof(future_state<>) <= 8, "future_state<> is too large");
476 static_assert(sizeof(future_state<long>) <= 16, "future_state<long> is too large");
477 
478 template <typename... T>
479 class continuation_base : public task {
480 protected:
481  future_state<T...> _state;
482  using future_type = future<T...>;
483  using promise_type = promise<T...>;
484 public:
485  continuation_base() = default;
486  explicit continuation_base(future_state<T...>&& state) : _state(std::move(state)) {}
487  void set_state(future_state<T...>&& state) {
488  _state = std::move(state);
489  }
490  friend class internal::promise_base_with_type<T...>;
491  friend class promise<T...>;
492  friend class future<T...>;
493 };
494 
495 template <typename Promise, typename... T>
496 class continuation_base_with_promise : public continuation_base<T...> {
497 protected:
498  continuation_base_with_promise(Promise&& pr, future_state<T...>&& state)
499  : continuation_base<T...>(std::move(state)), _pr(std::move(pr)) {}
500  continuation_base_with_promise(Promise&& pr) : _pr(std::move(pr)) {}
501  Promise _pr;
502 };
503 
504 template <typename Promise, typename Func, typename... T>
505 struct continuation final : continuation_base_with_promise<Promise, T...> {
506  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)) {}
507  continuation(Promise&& pr, Func&& func) : continuation_base_with_promise<Promise, T...>(std::move(pr)), _func(std::move(func)) {}
508  virtual void run_and_dispose() noexcept override {
509  _func(this->_pr, std::move(this->_state));
510  delete this;
511  }
512  Func _func;
513 };
514 
515 namespace internal {
516 
517 template <typename... T>
518 future<T...> make_exception_future(future_state_base&& state) noexcept;
519 
520 template <typename... T, typename U>
521 void set_callback(future<T...>& fut, U* callback) noexcept;
522 
523 class future_base;
524 
525 class promise_base {
526 protected:
527  enum class urgent { no, yes };
528  future_base* _future = nullptr;
529 
530  // This points to the future_state that is currently being
531  // used. See comment above the future_state struct definition for
532  // details.
533  future_state_base* _state;
534 
535  task* _task = nullptr;
536 
537  promise_base(const promise_base&) = delete;
538  promise_base(future_state_base* state) noexcept : _state(state) {}
539  promise_base(future_base* future, future_state_base* state) noexcept;
540  promise_base(promise_base&& x) noexcept;
541 
542  // We never need to destruct this polymorphicly, so we can make it
543  // protected instead of virtual
544  ~promise_base() noexcept;
545 
546  void operator=(const promise_base&) = delete;
547  promise_base& operator=(promise_base&& x) = delete;
548 
549  template<urgent Urgent>
550  void make_ready() noexcept;
551 
552  template<typename T>
553  void set_exception_impl(T&& val) noexcept {
554  if (_state) {
555  _state->set_exception(std::move(val));
556  make_ready<urgent::no>();
557  } else {
558  // We get here if promise::get_future is called and the
559  // returned future is destroyed without creating a
560  // continuation.
561  // In older versions of seastar we would store a local
562  // copy of ex and warn in the promise destructor.
563  // Since there isn't any way for the user to clear
564  // the exception, we issue the warning from here.
565  report_failed_future(val);
566  }
567  }
568 
569  void set_exception(future_state_base&& state) noexcept {
570  set_exception_impl(std::move(state));
571  }
572 
573  void set_exception(std::exception_ptr&& ex) noexcept {
574  set_exception_impl(std::move(ex));
575  }
576 
577  void set_exception(const std::exception_ptr& ex) noexcept {
578  set_exception(std::exception_ptr(ex));
579  }
580 
581  template<typename Exception>
582  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
583  set_exception(make_exception_ptr(std::forward<Exception>(e)));
584  }
585 
586  friend class future_base;
587  template <typename... U> friend class seastar::future;
588 };
589 
596 template <typename... T>
597 class promise_base_with_type : protected internal::promise_base {
598 protected:
599  future_state<T...>* get_state() {
600  return static_cast<future_state<T...>*>(_state);
601  }
602  static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
603 public:
604  promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
605  promise_base_with_type(future<T...>* future) noexcept : promise_base(future, &future->_state) { }
606  promise_base_with_type(promise_base_with_type&& x) noexcept : promise_base(std::move(x)) { }
607  promise_base_with_type(const promise_base_with_type&) = delete;
608  promise_base_with_type& operator=(promise_base_with_type&& x) noexcept {
609  this->~promise_base_with_type();
610  new (this) promise_base_with_type(std::move(x));
611  return *this;
612  }
613  void operator=(const promise_base_with_type&) = delete;
614 
615  void set_urgent_state(future_state<T...>&& state) noexcept {
616  auto* ptr = get_state();
617  // The state can be null if the corresponding future has been
618  // destroyed without producing a continuation.
619  if (ptr) {
620  // FIXME: This is a fairly expensive assert. It would be a
621  // good candidate for being disabled in release builds if
622  // we had such an assert.
623  assert(ptr->_u.st == future_state_base::state::future);
624  new (ptr) future_state<T...>(std::move(state));
625  make_ready<urgent::yes>();
626  }
627  }
628 
629  template <typename... A>
630  void set_value(A&&... a) {
631  if (auto *s = get_state()) {
632  s->set(std::forward<A>(a)...);
633  make_ready<urgent::no>();
634  }
635  }
636 
637 #if SEASTAR_COROUTINES_TS
638  void set_coroutine(future_state<T...>& state, task& coroutine) noexcept {
639  _state = &state;
640  _task = &coroutine;
641  }
642 #endif
643 private:
644  template <typename Pr, typename Func>
645  void schedule(Pr&& pr, Func&& func) noexcept {
646  auto tws = new continuation<Pr, Func, T...>(std::move(pr), std::move(func));
647  _state = &tws->_state;
648  _task = tws;
649  }
650  void schedule(continuation_base<T...>* callback) noexcept {
651  _state = &callback->_state;
652  _task = callback;
653  }
654 
655  template <typename... U>
656  friend class seastar::future;
657 
658  friend struct seastar::future_state<T...>;
659 };
660 }
662 
668 template <typename... T>
669 class promise : private internal::promise_base_with_type<T...> {
670  future_state<T...> _local_state;
671 
672 public:
676  promise() noexcept : internal::promise_base_with_type<T...>(&_local_state) {}
677 
679  promise(promise&& x) noexcept;
680  promise(const promise&) = delete;
681  promise& operator=(promise&& x) noexcept {
682  this->~promise();
683  new (this) promise(std::move(x));
684  return *this;
685  }
686  void operator=(const promise&) = delete;
687 
694  future<T...> get_future() noexcept;
695 
707  template <typename... A>
708  void set_value(A&&... a) {
709  internal::promise_base_with_type<T...>::set_value(std::forward<A>(a)...);
710  }
711 
716  void set_exception(std::exception_ptr&& ex) noexcept {
717  internal::promise_base::set_exception(std::move(ex));
718  }
719 
720  void set_exception(const std::exception_ptr& ex) noexcept {
721  internal::promise_base::set_exception(ex);
722  }
723 
728  template<typename Exception>
729  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
730  internal::promise_base::set_exception(std::forward<Exception>(e));
731  }
732 
733  using internal::promise_base_with_type<T...>::set_urgent_state;
734 
735  template <typename... U>
736  friend class future;
737 };
738 
744 template<>
745 class promise<void> : public promise<> {};
746 
748 
751 
752 
758 template <typename... T> struct is_future : std::false_type {};
759 
762 template <typename... T> struct is_future<future<T...>> : std::true_type {};
763 
765 
766 
770 template <typename T>
771 struct futurize;
772 
773 template <typename T>
774 struct futurize {
776  using type = future<T>;
780  using value_type = std::tuple<T>;
781 
784  template<typename Func, typename... FuncArgs>
785  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
786 
789  template<typename Func, typename... FuncArgs>
790  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
791 
793  template<typename Func, typename... FuncArgs>
794  [[deprecated("Use invoke for varargs")]]
795  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
796 
798  static inline type convert(T&& value) { return make_ready_future<T>(std::move(value)); }
799  static inline type convert(type&& value) { return std::move(value); }
800 
802  static type from_tuple(value_type&& value);
804  static type from_tuple(const value_type& value);
805 
807  template <typename Arg>
808  static type make_exception_future(Arg&& arg) noexcept;
809 };
810 
812 template <>
813 struct futurize<void> {
814  using type = future<>;
815  using promise_type = promise<>;
816  using value_type = std::tuple<>;
817 
818  template<typename Func, typename... FuncArgs>
819  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
820 
821  template<typename Func, typename... FuncArgs>
822  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
823 
824  template<typename Func, typename... FuncArgs>
825  [[deprecated("Use invoke for varargs")]]
826  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
827 
828  static inline type from_tuple(value_type&& value);
829  static inline type from_tuple(const value_type& value);
830 
831  template <typename Arg>
832  static type make_exception_future(Arg&& arg) noexcept;
833 };
834 
835 template <typename... Args>
836 struct futurize<future<Args...>> {
837  using type = future<Args...>;
838  using promise_type = promise<Args...>;
839  using value_type = std::tuple<Args...>;
840 
841  template<typename Func, typename... FuncArgs>
842  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
843 
844  template<typename Func, typename... FuncArgs>
845  static inline type invoke(Func&& func, FuncArgs&&... args) noexcept;
846 
847  template<typename Func, typename... FuncArgs>
848  [[deprecated("Use invoke for varargs")]]
849  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
850 
851  static inline type from_tuple(value_type&& value);
852  static inline type from_tuple(const value_type& value);
853 
854  static inline type convert(Args&&... values) { return make_ready_future<Args...>(std::move(values)...); }
855  static inline type convert(type&& value) { return std::move(value); }
856 
857  template <typename Arg>
858  static type make_exception_future(Arg&& arg) noexcept;
859 };
861 
862 // Converts a type to a future type, if it isn't already.
863 template <typename T>
864 using futurize_t = typename futurize<T>::type;
865 
867 
868 template<typename Func, typename... Args>
869 auto futurize_invoke(Func&& func, Args&&... args);
870 
871 template<typename Func, typename... Args>
872 auto futurize_apply(Func&& func, std::tuple<Args...>&& args);
873 
874 GCC6_CONCEPT(
875 
876 template <typename T>
877 concept bool Future = is_future<T>::value;
878 
879 template <typename Func, typename... T>
880 concept bool CanApply = requires (Func f, T... args) {
881  f(std::forward<T>(args)...);
882 };
883 
884 template <typename Func, typename Return, typename... T>
885 concept bool ApplyReturns = requires (Func f, T... args) {
886  { f(std::forward<T>(args)...) } -> Return;
887 };
888 
889 template <typename Func, typename... T>
890 concept bool ApplyReturnsAnyFuture = requires (Func f, T... args) {
891  requires is_future<decltype(f(std::forward<T>(args)...))>::value;
892 };
893 
894 )
895 
898 namespace internal {
899 class future_base {
900 protected:
901  promise_base* _promise;
902  future_base() noexcept : _promise(nullptr) {}
903  future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
904  _promise->_future = this;
905  _promise->_state = state;
906  }
907 
908  future_base(future_base&& x, future_state_base* state) noexcept : _promise(x._promise) {
909  if (auto* p = _promise) {
910  x.detach_promise();
911  p->_future = this;
912  p->_state = state;
913  }
914  }
915  ~future_base() noexcept {
916  if (_promise) {
917  detach_promise();
918  }
919  }
920 
921  promise_base* detach_promise() noexcept {
922  _promise->_state = nullptr;
923  _promise->_future = nullptr;
924  return std::exchange(_promise, nullptr);
925  }
926 
927  friend class promise_base;
928 };
929 
930 template <bool IsVariadic>
931 struct warn_variadic_future {
932  // Non-varidic case, do nothing
933  void check_deprecation() {}
934 };
935 
936 
937 // Note: placing the deprecated attribute on the class specialization has no effect.
938 template <>
939 struct warn_variadic_future<true> {
940  // Variadic case, has deprecation attribute
941  [[deprecated("Variadic future<> with more than one template parmeter is deprecated, replace with future<std::tuple<...>>")]]
942  void check_deprecation() {}
943 };
944 
945 }
946 
989 template <typename... T>
990 class SEASTAR_NODISCARD future : private internal::future_base, internal::warn_variadic_future<(sizeof...(T) > 1)> {
991  future_state<T...> _state;
992  static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
993 private:
994  // This constructor creates a future that is not ready but has no
995  // associated promise yet. The use case is to have a less flexible
996  // but more efficient future/promise pair where we know that
997  // promise::set_value cannot possibly be called without a matching
998  // future and so that promise doesn't need to store a
999  // future_state.
1000  future(future_for_get_promise_marker m) { }
1001 
1002  future(promise<T...>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
1003  template <typename... A>
1004  future(ready_future_marker m, A&&... a) : _state(m, std::forward<A>(a)...) { }
1005  future(exception_future_marker m, std::exception_ptr&& ex) noexcept : _state(m, std::move(ex)) { }
1006  future(exception_future_marker m, future_state_base&& state) noexcept : _state(m, std::move(state)) { }
1007  [[gnu::always_inline]]
1008  explicit future(future_state<T...>&& state) noexcept
1009  : _state(std::move(state)) {
1010  this->check_deprecation();
1011  }
1012  internal::promise_base_with_type<T...> get_promise() noexcept {
1013  assert(!_promise);
1014  return internal::promise_base_with_type<T...>(this);
1015  }
1016  internal::promise_base_with_type<T...>* detach_promise() {
1017  return static_cast<internal::promise_base_with_type<T...>*>(future_base::detach_promise());
1018  }
1019  template <typename Pr, typename Func>
1020  void schedule(Pr&& pr, Func&& func) noexcept {
1021  if (_state.available() || !_promise) {
1022  if (__builtin_expect(!_state.available() && !_promise, false)) {
1023  _state.set_to_broken_promise();
1024  }
1025  ::seastar::schedule(new continuation<Pr, Func, T...>(std::move(pr), std::move(func), std::move(_state)));
1026  } else {
1027  assert(_promise);
1028  detach_promise()->schedule(std::move(pr), std::move(func));
1029  _state._u.st = future_state_base::state::invalid;
1030  }
1031  }
1032 
1033  [[gnu::always_inline]]
1034  future_state<T...>&& get_available_state_ref() noexcept {
1035  if (_promise) {
1036  detach_promise();
1037  }
1038  return std::move(_state);
1039  }
1040 
1041  [[gnu::noinline]]
1042  future<T...> rethrow_with_nested() {
1043  if (!failed()) {
1044  return internal::current_exception_as_future<T...>();
1045  } else {
1046  //
1047  // Encapsulate the current exception into the
1048  // std::nested_exception because the current libstdc++
1049  // implementation has a bug requiring the value of a
1050  // std::throw_with_nested() parameter to be of a polymorphic
1051  // type.
1052  //
1053  std::nested_exception f_ex;
1054  try {
1055  get();
1056  } catch (...) {
1057  std::throw_with_nested(f_ex);
1058  }
1059  __builtin_unreachable();
1060  }
1061  }
1062 
1063  template<typename... U>
1064  friend class shared_future;
1065 public:
1067  using value_type = std::tuple<T...>;
1069  using promise_type = promise<T...>;
1071  [[gnu::always_inline]]
1072  future(future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1073  future(const future&) = delete;
1074  future& operator=(future&& x) noexcept {
1075  this->~future();
1076  new (this) future(std::move(x));
1077  return *this;
1078  }
1079  void operator=(const future&) = delete;
1089  [[gnu::always_inline]]
1090  std::tuple<T...>&& get() {
1091  if (!_state.available()) {
1092  do_wait();
1093  }
1094  return get_available_state_ref().take();
1095  }
1096 
1097  [[gnu::always_inline]]
1098  std::exception_ptr get_exception() {
1099  return get_available_state_ref().get_exception();
1100  }
1101 
1110  typename future_state<T...>::get0_return_type get0() {
1111  return future_state<T...>::get0(get());
1112  }
1113 
1119  void wait() noexcept {
1120  if (!_state.available()) {
1121  do_wait();
1122  }
1123  }
1124 private:
1125  class thread_wake_task final : public continuation_base<T...> {
1126  thread_context* _thread;
1127  future* _waiting_for;
1128  public:
1129  thread_wake_task(thread_context* thread, future* waiting_for)
1130  : _thread(thread), _waiting_for(waiting_for) {
1131  }
1132  virtual void run_and_dispose() noexcept override {
1133  _waiting_for->_state = std::move(this->_state);
1134  thread_impl::switch_in(_thread);
1135  // no need to delete, since this is always allocated on
1136  // _thread's stack.
1137  }
1138  };
1139  void do_wait() noexcept {
1140  if (__builtin_expect(!_promise, false)) {
1141  _state.set_to_broken_promise();
1142  return;
1143  }
1144  auto thread = thread_impl::get();
1145  assert(thread);
1146  thread_wake_task wake_task{thread, this};
1147  detach_promise()->schedule(static_cast<continuation_base<T...>*>(&wake_task));
1148  thread_impl::switch_out(thread);
1149  }
1150 
1151 public:
1155  [[gnu::always_inline]]
1156  bool available() const noexcept {
1157  return _state.available();
1158  }
1159 
1163  [[gnu::always_inline]]
1164  bool failed() const noexcept {
1165  return _state.failed();
1166  }
1167 
1183  template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1184  GCC6_CONCEPT( requires ::seastar::CanApply<Func, T...> )
1185  Result
1186  then(Func&& func) noexcept {
1187 #ifndef SEASTAR_TYPE_ERASE_MORE
1188  return then_impl(std::move(func));
1189 #else
1190  return then_impl(noncopyable_function<Result (T&&...)>([func = std::forward<Func>(func)] (T&&... args) mutable {
1191  return futurize_apply(func, std::forward_as_tuple(std::move(args)...));
1192  }));
1193 #endif
1194  }
1195 
1196 private:
1197 
1198  // Keep this simple so that Named Return Value Optimization is used.
1199  template <typename Func, typename Result>
1200  Result then_impl_nrvo(Func&& func) noexcept {
1201  using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1202  typename futurator::type fut(future_for_get_promise_marker{});
1203  // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1204  // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1205  // that happens.
1206  [&] () noexcept {
1207  using pr_type = decltype(fut.get_promise());
1208  memory::disable_failure_guard dfg;
1209  schedule(fut.get_promise(), [func = std::forward<Func>(func)] (pr_type& pr, future_state<T...>&& state) mutable {
1210  if (state.failed()) {
1211  pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1212  } else {
1213  futurator::apply(std::forward<Func>(func), std::move(state).get_value()).forward_to(std::move(pr));
1214  }
1215  });
1216  } ();
1217  return fut;
1218  }
1219 
1220  template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1221  Result
1222  then_impl(Func&& func) noexcept {
1223  using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1224  if (available() && !need_preempt()) {
1225  if (failed()) {
1226  return futurator::make_exception_future(static_cast<future_state_base&&>(get_available_state_ref()));
1227  } else {
1228  return futurator::apply(std::forward<Func>(func), get_available_state_ref().take_value());
1229  }
1230  }
1231  return then_impl_nrvo<Func, Result>(std::forward<Func>(func));
1232  }
1233 
1234 public:
1250  template <typename Func, typename FuncResult = std::result_of_t<Func(future)>>
1251  GCC6_CONCEPT( requires ::seastar::CanApply<Func, future> )
1252  futurize_t<FuncResult>
1253  then_wrapped(Func&& func) & noexcept {
1254  return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1255  }
1256 
1257  template <typename Func, typename FuncResult = std::result_of_t<Func(future&&)>>
1258  GCC6_CONCEPT( requires ::seastar::CanApply<Func, future&&> )
1259  futurize_t<FuncResult>
1260  then_wrapped(Func&& func) && noexcept {
1261  return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1262  }
1263 
1264 private:
1265 
1266  template <bool AsSelf, typename FuncResult, typename Func>
1267  futurize_t<FuncResult>
1268  then_wrapped_maybe_erase(Func&& func) noexcept {
1269 #ifndef SEASTAR_TYPE_ERASE_MORE
1270  return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1271 #else
1272  using futurator = futurize<FuncResult>;
1273  using WrapFuncResult = typename futurator::type;
1274  return then_wrapped_common<AsSelf, WrapFuncResult>(noncopyable_function<WrapFuncResult (future&&)>([func = std::forward<Func>(func)] (future&& f) mutable {
1275  return futurator::invoke(std::forward<Func>(func), std::move(f));
1276  }));
1277 #endif
1278  }
1279 
1280  // Keep this simple so that Named Return Value Optimization is used.
1281  template <typename FuncResult, typename Func>
1282  futurize_t<FuncResult>
1283  then_wrapped_nrvo(Func&& func) noexcept {
1284  using futurator = futurize<FuncResult>;
1285  typename futurator::type fut(future_for_get_promise_marker{});
1286  // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1287  // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1288  // that happens.
1289  [&] () noexcept {
1290  using pr_type = decltype(fut.get_promise());
1291  memory::disable_failure_guard dfg;
1292  schedule(fut.get_promise(), [func = std::forward<Func>(func)] (pr_type& pr, future_state<T...>&& state) mutable {
1293  futurator::invoke(std::forward<Func>(func), future(std::move(state))).forward_to(std::move(pr));
1294  });
1295  } ();
1296  return fut;
1297  }
1298 
1299 
1300  template <bool AsSelf, typename FuncResult, typename Func>
1301  futurize_t<FuncResult>
1302  then_wrapped_common(Func&& func) noexcept {
1303  using futurator = futurize<FuncResult>;
1304  if (available() && !need_preempt()) {
1305  // TODO: after dropping C++14 support use `if constexpr ()` instead.
1306  if (AsSelf) {
1307  if (_promise) {
1308  detach_promise();
1309  }
1310  return futurator::invoke(std::forward<Func>(func), std::move(*this));
1311  } else {
1312  return futurator::invoke(std::forward<Func>(func), future(get_available_state_ref()));
1313  }
1314  }
1315  return then_wrapped_nrvo<FuncResult, Func>(std::forward<Func>(func));
1316  }
1317 
1318  void forward_to(internal::promise_base_with_type<T...>&& pr) noexcept {
1319  if (_state.available()) {
1320  pr.set_urgent_state(std::move(_state));
1321  } else {
1322  *detach_promise() = std::move(pr);
1323  }
1324  }
1325 
1326 public:
1337  void forward_to(promise<T...>&& pr) noexcept {
1338  if (_state.available()) {
1339  pr.set_urgent_state(std::move(_state));
1340  } else if (&pr._local_state != pr._state) {
1341  // The only case when _state points to _local_state is
1342  // when get_future was never called. Given that pr will
1343  // soon be destroyed, we know get_future will never be
1344  // called and we can just ignore this request.
1345  *detach_promise() = std::move(pr);
1346  }
1347  }
1348 
1349 
1350 
1366  template <typename Func>
1367  GCC6_CONCEPT( requires ::seastar::CanApply<Func> )
1368  future<T...> finally(Func&& func) noexcept {
1369  return then_wrapped(finally_body<Func, is_future<std::result_of_t<Func()>>::value>(std::forward<Func>(func)));
1370  }
1371 
1372 
1373  template <typename Func, bool FuncReturnsFuture>
1375 
1376  template <typename Func>
1377  struct finally_body<Func, true> {
1378  Func _func;
1379 
1380  finally_body(Func&& func) : _func(std::forward<Func>(func))
1381  { }
1382 
1383  future<T...> operator()(future<T...>&& result) {
1384  return futurize_invoke(_func).then_wrapped([result = std::move(result)](auto f_res) mutable {
1385  if (!f_res.failed()) {
1386  return std::move(result);
1387  } else {
1388  try {
1389  f_res.get();
1390  } catch (...) {
1391  return result.rethrow_with_nested();
1392  }
1393  __builtin_unreachable();
1394  }
1395  });
1396  }
1397  };
1398 
1399  template <typename Func>
1400  struct finally_body<Func, false> {
1401  Func _func;
1402 
1403  finally_body(Func&& func) : _func(std::forward<Func>(func))
1404  { }
1405 
1406  future<T...> operator()(future<T...>&& result) {
1407  try {
1408  _func();
1409  return std::move(result);
1410  } catch (...) {
1411  return result.rethrow_with_nested();
1412  }
1413  };
1414  };
1415 
1420  future<> or_terminate() noexcept {
1421  return then_wrapped([] (auto&& f) {
1422  try {
1423  f.get();
1424  } catch (...) {
1425  engine_exit(std::current_exception());
1426  }
1427  });
1428  }
1429 
1435  return then([] (T&&...) {});
1436  }
1437 
1451  template <typename Func>
1452  /* Broken?
1453  GCC6_CONCEPT( requires ::seastar::ApplyReturns<Func, future<T...>, std::exception_ptr>
1454  || (sizeof...(T) == 0 && ::seastar::ApplyReturns<Func, void, std::exception_ptr>)
1455  || (sizeof...(T) == 1 && ::seastar::ApplyReturns<Func, T..., std::exception_ptr>)
1456  ) */
1457  future<T...> handle_exception(Func&& func) noexcept {
1458  return then_wrapped([func = std::forward<Func>(func)]
1459  (auto&& fut) mutable -> future<T...> {
1460  if (!fut.failed()) {
1461  return make_ready_future<T...>(fut.get());
1462  } else {
1463  return futurize_invoke(func, fut.get_exception());
1464  }
1465  });
1466  }
1467 
1478  template <typename Func>
1479  future<T...> handle_exception_type(Func&& func) noexcept {
1480  using trait = function_traits<Func>;
1481  static_assert(trait::arity == 1, "func can take only one parameter");
1482  using ex_type = typename trait::template arg<0>::type;
1483  return then_wrapped([func = std::forward<Func>(func)]
1484  (auto&& fut) mutable -> future<T...> {
1485  try {
1486  return make_ready_future<T...>(fut.get());
1487  } catch(ex_type& ex) {
1488  return futurize_invoke(func, ex);
1489  }
1490  });
1491  }
1492 
1498  void ignore_ready_future() noexcept {
1499  _state.ignore();
1500  }
1501 
1502 #if SEASTAR_COROUTINES_TS
1503  void set_coroutine(task& coroutine) noexcept {
1504  assert(!_state.available());
1505  assert(_promise);
1506  detach_promise()->set_coroutine(_state, coroutine);
1507  }
1508 #endif
1509 private:
1510  void set_callback(continuation_base<T...>* callback) noexcept {
1511  if (_state.available()) {
1512  callback->set_state(get_available_state_ref());
1513  ::seastar::schedule(callback);
1514  } else {
1515  assert(_promise);
1516  detach_promise()->schedule(callback);
1517  }
1518 
1519  }
1520 
1522  template <typename... U>
1523  friend class future;
1524  template <typename... U>
1525  friend class promise;
1526  template <typename... U>
1527  friend class internal::promise_base_with_type;
1528  template <typename... U, typename... A>
1529  friend future<U...> make_ready_future(A&&... value);
1530  template <typename... U>
1531  friend future<U...> make_exception_future(std::exception_ptr&& ex) noexcept;
1532  template <typename... U, typename Exception>
1533  friend future<U...> make_exception_future(Exception&& ex) noexcept;
1534  template <typename... U>
1535  friend future<U...> internal::make_exception_future(future_state_base&& state) noexcept;
1536  template <typename... U, typename V>
1537  friend void internal::set_callback(future<U...>&, V*) noexcept;
1539 };
1540 
1541 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1542  : _future(future), _state(state) {
1543  _future->_promise = this;
1544 }
1545 
1546 template <typename... T>
1547 inline
1548 future<T...>
1550  assert(!this->_future && this->_state && !this->_task);
1551  return future<T...>(this);
1552 }
1553 
1554 template <typename... T>
1555 inline
1556 promise<T...>::promise(promise&& x) noexcept : internal::promise_base_with_type<T...>(std::move(x)) {
1557  if (this->_state == &x._local_state) {
1558  this->_state = &_local_state;
1559  _local_state = std::move(x._local_state);
1560  }
1561 }
1562 
1563 template <typename... T, typename... A>
1564 inline
1565 future<T...> make_ready_future(A&&... value) {
1566  return future<T...>(ready_future_marker(), std::forward<A>(value)...);
1567 }
1568 
1569 template <typename... T>
1570 inline
1571 future<T...> make_exception_future(std::exception_ptr&& ex) noexcept {
1572  return future<T...>(exception_future_marker(), std::move(ex));
1573 }
1574 
1575 template <typename... T>
1576 inline
1577 future<T...> internal::make_exception_future(future_state_base&& state) noexcept {
1578  return future<T...>(exception_future_marker(), std::move(state));
1579 }
1580 
1581 template <typename... T>
1582 future<T...> internal::current_exception_as_future() noexcept {
1583  return internal::make_exception_future<T...>(future_state_base::current_exception());
1584 }
1585 
1586 void log_exception_trace() noexcept;
1587 
1594 template <typename... T, typename Exception>
1595 inline
1596 future<T...> make_exception_future(Exception&& ex) noexcept {
1597  log_exception_trace();
1598  return make_exception_future<T...>(std::make_exception_ptr(std::forward<Exception>(ex)));
1599 }
1600 
1602 
1604 
1605 template<typename T>
1606 template<typename Func, typename... FuncArgs>
1607 typename futurize<T>::type futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1608  try {
1609  return convert(::seastar::apply(std::forward<Func>(func), std::move(args)));
1610  } catch (...) {
1611  return internal::current_exception_as_future<T>();
1612  }
1613 }
1614 
1615 template<typename T>
1616 template<typename Func, typename... FuncArgs>
1617 typename futurize<T>::type futurize<T>::invoke(Func&& func, FuncArgs&&... args) noexcept {
1618  try {
1619  return convert(func(std::forward<FuncArgs>(args)...));
1620  } catch (...) {
1621  return internal::current_exception_as_future<T>();
1622  }
1623 }
1624 
1625 template<typename T>
1626 template<typename Func, typename... FuncArgs>
1627 typename futurize<T>::type futurize<T>::apply(Func&& func, FuncArgs&&... args) noexcept {
1628  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1629 }
1630 
1631 template<typename Func, typename... FuncArgs>
1632 typename futurize<void>::type futurize<void>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1633  try {
1634  ::seastar::apply(std::forward<Func>(func), std::move(args));
1635  return make_ready_future<>();
1636  } catch (...) {
1637  return internal::current_exception_as_future<>();
1638  }
1639 }
1640 
1641 template<typename Func, typename... FuncArgs>
1642 typename futurize<void>::type futurize<void>::invoke(Func&& func, FuncArgs&&... args) noexcept {
1643  try {
1644  func(std::forward<FuncArgs>(args)...);
1645  return make_ready_future<>();
1646  } catch (...) {
1647  return internal::current_exception_as_future<>();
1648  }
1649 }
1650 
1651 template<typename Func, typename... FuncArgs>
1652 typename futurize<void>::type futurize<void>::apply(Func&& func, FuncArgs&&... args) noexcept {
1653  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1654 }
1655 
1656 template<typename... Args>
1657 template<typename Func, typename... FuncArgs>
1658 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1659  try {
1660  return ::seastar::apply(std::forward<Func>(func), std::move(args));
1661  } catch (...) {
1662  return internal::current_exception_as_future<Args...>();
1663  }
1664 }
1665 
1666 template<typename... Args>
1667 template<typename Func, typename... FuncArgs>
1668 typename futurize<future<Args...>>::type futurize<future<Args...>>::invoke(Func&& func, FuncArgs&&... args) noexcept {
1669  try {
1670  return func(std::forward<FuncArgs>(args)...);
1671  } catch (...) {
1672  return internal::current_exception_as_future<Args...>();
1673  }
1674 }
1675 
1676 template<typename... Args>
1677 template<typename Func, typename... FuncArgs>
1678 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, FuncArgs&&... args) noexcept {
1679  return invoke(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1680 }
1681 
1682 template <typename T>
1683 template <typename Arg>
1684 inline
1685 future<T>
1686 futurize<T>::make_exception_future(Arg&& arg) noexcept {
1689  return make_exception_future<T>(std::forward<Arg>(arg));
1690 }
1691 
1692 template <typename... T>
1693 template <typename Arg>
1694 inline
1695 future<T...>
1696 futurize<future<T...>>::make_exception_future(Arg&& arg) noexcept {
1699  return make_exception_future<T...>(std::forward<Arg>(arg));
1700 }
1701 
1702 template <typename Arg>
1703 inline
1704 future<>
1705 futurize<void>::make_exception_future(Arg&& arg) noexcept {
1708  return make_exception_future<>(std::forward<Arg>(arg));
1709 }
1710 
1711 template <typename T>
1712 inline
1713 future<T>
1714 futurize<T>::from_tuple(std::tuple<T>&& value) {
1715  return make_ready_future<T>(std::move(value));
1716 }
1717 
1718 template <typename T>
1719 inline
1720 future<T>
1721 futurize<T>::from_tuple(const std::tuple<T>& value) {
1722  return make_ready_future<T>(value);
1723 }
1724 
1725 inline
1726 future<>
1727 futurize<void>::from_tuple(std::tuple<>&& value) {
1728  return make_ready_future<>();
1729 }
1730 
1731 inline
1732 future<>
1733 futurize<void>::from_tuple(const std::tuple<>& value) {
1734  return make_ready_future<>();
1735 }
1736 
1737 template <typename... Args>
1738 inline
1739 future<Args...>
1740 futurize<future<Args...>>::from_tuple(std::tuple<Args...>&& value) {
1741  return make_ready_future<Args...>(std::move(value));
1742 }
1743 
1744 template <typename... Args>
1745 inline
1746 future<Args...>
1747 futurize<future<Args...>>::from_tuple(const std::tuple<Args...>& value) {
1748  return make_ready_future<Args...>(value);
1749 }
1750 
1751 template<typename Func, typename... Args>
1752 auto futurize_invoke(Func&& func, Args&&... args) {
1753  using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
1754  return futurator::invoke(std::forward<Func>(func), std::forward<Args>(args)...);
1755 }
1756 
1757 template<typename Func, typename... Args>
1758 [[deprecated("Use futurize_invoke for varargs")]]
1759 auto futurize_apply(Func&& func, Args&&... args) {
1760  return futurize_invoke(std::forward<Func>(func), std::forward<Args>(args)...);
1761 }
1762 
1763 template<typename Func, typename... Args>
1764 auto futurize_apply(Func&& func, std::tuple<Args...>&& args) {
1765  using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
1766  return futurator::apply(std::forward<Func>(func), std::move(args));
1767 }
1768 
1769 namespace internal {
1770 
1771 template <typename... T, typename U>
1772 inline
1773 void set_callback(future<T...>& fut, U* callback) noexcept {
1774  // It would be better to use continuation_base<T...> for U, but
1775  // then a derived class of continuation_base<T...> won't be matched
1776  return fut.set_callback(callback);
1777 }
1778 
1779 }
1780 
1781 
1783 
1784 }
future< T... > handle_exception_type(Func &&func) noexcept
Handle the exception of a certain type carried by this future.
Definition: future.hh:1479
future< T... > make_ready_future(A &&... value)
Creates a future in an available, value state.
Definition: future.hh:1565
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:1253
Definition: noncopyable_function.hh:33
Definition: future.hh:378
A representation of a possibly not-yet-computed value.
Definition: future.hh:79
future< T... > make_exception_future(std::exception_ptr &&value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1571
void wait() noexcept
Definition: future.hh:1119
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:716
promise() noexcept
Constructs an empty promise.
Definition: future.hh:676
Definition: future.hh:285
Check whether a type is a future.
Definition: future.hh:758
bool failed() const noexcept
Checks whether the future has failed.
Definition: future.hh:1164
STL namespace.
static type apply(Func &&func, std::tuple< FuncArgs... > &&args) noexcept
thread - stateful thread of execution
Definition: thread.hh:141
Exception type for broken promises.
Definition: future.hh:129
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:771
void forward_to(promise< T... > &&pr) noexcept
Satisfy some promise object with this future as a result.
Definition: future.hh:1337
promise - allows a future value to be made available at a later time.
Definition: future.hh:76
std::tuple< T > value_type
The value tuple type associated with type.
Definition: future.hh:780
bool available() const noexcept
Checks whether the future is available.
Definition: future.hh:1156
future< T... > handle_exception(Func &&func) noexcept
Handle the exception carried by this future.
Definition: future.hh:1457
future_state< T... >::get0_return_type get0()
Definition: future.hh:1110
Definition: future.hh:1374
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:798
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:1186
future< T > type
If T is a future, T; otherwise future<T>
Definition: future.hh:776
Definition: future.hh:265
future< T... > get_future() noexcept
Gets the promise&#39;s associated future.
Definition: future.hh:1549
Definition: task.hh:29
Definition: future.hh:379
future< T... > make_exception_future(Exception &&ex) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1596
future(future &&x) noexcept
Moves the future into a new object.
Definition: future.hh:1072
std::tuple< T... > value_type
The data type carried by the future.
Definition: future.hh:1067
Like future except the result can be waited for by many fibers.
Definition: future.hh:82
future or_terminate() noexcept
Terminate the program if this future fails.
Definition: future.hh:1420
future discard_result() noexcept
Discards the value carried by this future.
Definition: future.hh:1434
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:729
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
void ignore_ready_future() noexcept
Ignore any result hold by this future.
Definition: future.hh:1498