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 
90 template <typename... T, typename... A>
91 future<T...> make_ready_future(A&&... value);
92 
99 template <typename... T>
100 future<T...> make_exception_future(std::exception_ptr value) noexcept;
101 
103 void engine_exit(std::exception_ptr eptr = {});
104 
105 void report_failed_future(const std::exception_ptr& ex) noexcept;
107 
114 struct broken_promise : std::logic_error {
115  broken_promise();
116 };
117 
118 namespace internal {
119 template <class... T>
120 class promise_base_with_type;
121 
122 // 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
123 // fails the build even if it is in the non enabled side of std::conditional.
124 template <typename... T>
125 struct get0_return_type {
126  using type = void;
127  static type get0(std::tuple<T...> v) { }
128 };
129 
130 template <typename T0, typename... T>
131 struct get0_return_type<T0, T...> {
132  using type = T0;
133  static type get0(std::tuple<T0, T...> v) { return std::get<0>(std::move(v)); }
134 };
135 
143 template <typename T, bool is_trivial_class>
144 struct uninitialized_wrapper_base;
145 
146 template <typename T>
147 struct uninitialized_wrapper_base<T, false> {
148  union any {
149  any() {}
150  ~any() {}
151  T value;
152  } _v;
153 
154 public:
155  void uninitialized_set(T v) {
156  new (&_v.value) T(std::move(v));
157  }
158  T& uninitialized_get() {
159  return _v.value;
160  }
161  const T& uninitialized_get() const {
162  return _v.value;
163  }
164 };
165 
166 template <typename T> struct uninitialized_wrapper_base<T, true> : private T {
167  void uninitialized_set(T v) {
168  new (this) T(std::move(v));
169  }
170  T& uninitialized_get() {
171  return *this;
172  }
173  const T& uninitialized_get() const {
174  return *this;
175  }
176 };
177 
178 template <typename T>
179 constexpr bool can_inherit =
180 #ifdef _LIBCPP_VERSION
181 // We expect std::tuple<> to be trivially constructible and
182 // destructible. That is not the case with libc++
183 // (https://bugs.llvm.org/show_bug.cgi?id=41714). We could avoid this
184 // optimization when using libc++ and relax the asserts, but
185 // inspection suggests that std::tuple<> is trivial, it is just not
186 // marked as such.
187  std::is_same<std::tuple<>, T>::value ||
188 #endif
189  (std::is_trivially_destructible<T>::value && std::is_trivially_constructible<T>::value &&
190  std::is_class<T>::value && !std::is_final<T>::value);
191 
192 // The objective is to avoid extra space for empty types like std::tuple<>. We could use std::is_empty_v, but it is
193 // better to check that both the constructor and destructor can be skipped.
194 template <typename T>
195 struct uninitialized_wrapper
196  : public uninitialized_wrapper_base<T, can_inherit<T>> {};
197 
198 static_assert(std::is_empty<uninitialized_wrapper<std::tuple<>>>::value, "This should still be empty");
199 }
200 
201 //
202 // A future/promise pair maintain one logical value (a future_state).
203 // There are up to three places that can store it, but only one is
204 // active at any time.
205 //
206 // - in the promise _local_state member variable
207 //
208 // This is necessary because a promise is created first and there
209 // would be nowhere else to put the value.
210 //
211 // - in the future _state variable
212 //
213 // This is used anytime a future exists and then has not been called
214 // yet. This guarantees a simple access to the value for any code
215 // that already has a future.
216 //
217 // - in the task associated with the .then() clause (after .then() is called,
218 // if a value was not set)
219 //
220 //
221 // The promise maintains a pointer to the state, which is modified as
222 // the state moves to a new location due to events (such as .then() or
223 // get_future being called) or due to the promise or future being
224 // moved around.
225 //
226 
227 // non templated base class to reduce code duplication
229  static_assert(std::is_nothrow_copy_constructible<std::exception_ptr>::value,
230  "std::exception_ptr's copy constructor must not throw");
231  static_assert(std::is_nothrow_move_constructible<std::exception_ptr>::value,
232  "std::exception_ptr's move constructor must not throw");
233  static_assert(sizeof(std::exception_ptr) == sizeof(void*), "exception_ptr not a pointer");
234  enum class state : uintptr_t {
235  invalid = 0,
236  future = 1,
237  result = 2,
238  exception_min = 3, // or anything greater
239  };
240  union any {
241  any() { st = state::future; }
242  any(state s) { st = s; }
243  void set_exception(std::exception_ptr&& e) {
244  new (&ex) std::exception_ptr(std::move(e));
245  assert(st >= state::exception_min);
246  }
247  any(std::exception_ptr&& e) {
248  set_exception(std::move(e));
249  }
250  ~any() {}
251  std::exception_ptr take_exception() {
252  std::exception_ptr ret(std::move(ex));
253  // Unfortunately in libstdc++ ~exception_ptr is defined out of line. We know that it does nothing for
254  // moved out values, so we omit calling it. This is critical for the code quality produced for this
255  // function. Without the out of line call, gcc can figure out that both sides of the if produce
256  // identical code and merges them.if
257  // We don't make any assumptions about other c++ libraries.
258  // There is request with gcc to define it inline: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90295
259 #ifndef __GLIBCXX__
260  ex.~exception_ptr();
261 #endif
262  st = state::invalid;
263  return ret;
264  }
265  any(any&& x) {
266  if (x.st < state::exception_min) {
267  st = x.st;
268  } else {
269  new (&ex) std::exception_ptr(x.take_exception());
270  }
271  x.st = state::invalid;
272  }
273  state st;
274  std::exception_ptr ex;
275  } _u;
276 
277  future_state_base() noexcept { }
278  future_state_base(state st) noexcept : _u(st) { }
279  future_state_base(std::exception_ptr&& ex) noexcept : _u(std::move(ex)) { }
280  future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
281 
282  // We never need to destruct this polymorphicly, so we can make it
283  // protected instead of virtual.
284 protected:
285  ~future_state_base() noexcept {
286  if (failed()) {
287  report_failed_future(_u.take_exception());
288  }
289  }
290 
291 public:
292 
293  bool available() const noexcept { return _u.st == state::result || _u.st >= state::exception_min; }
294  bool failed() const noexcept { return __builtin_expect(_u.st >= state::exception_min, false); }
295 
296  void set_to_broken_promise() noexcept;
297 
298  void set_exception(std::exception_ptr&& ex) noexcept {
299  assert(_u.st == state::future);
300  _u.set_exception(std::move(ex));
301  }
302  std::exception_ptr get_exception() && noexcept {
303  assert(_u.st >= state::exception_min);
304  // Move ex out so future::~future() knows we've handled it
305  return _u.take_exception();
306  }
307  const std::exception_ptr& get_exception() const& noexcept {
308  assert(_u.st >= state::exception_min);
309  return _u.ex;
310  }
311 };
312 
316 
318 template <typename... T>
319 struct future_state : public future_state_base, private internal::uninitialized_wrapper<std::tuple<T...>> {
320  static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible<std::tuple<T...>>::value;
321  static_assert(std::is_nothrow_move_constructible<std::tuple<T...>>::value,
322  "Types must be no-throw move constructible");
323  static_assert(std::is_nothrow_destructible<std::tuple<T...>>::value,
324  "Types must be no-throw destructible");
325  future_state() noexcept {}
326  [[gnu::always_inline]]
327  future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
328  if (_u.st == state::result) {
329  this->uninitialized_set(std::move(x.uninitialized_get()));
330  x.uninitialized_get().~tuple();
331  }
332  }
333  __attribute__((always_inline))
334  ~future_state() noexcept {
335  if (_u.st == state::result) {
336  this->uninitialized_get().~tuple();
337  }
338  }
339  future_state& operator=(future_state&& x) noexcept {
340  this->~future_state();
341  new (this) future_state(std::move(x));
342  return *this;
343  }
344  template <typename... A>
345  future_state(ready_future_marker, A&&... a) : future_state_base(state::result) {
346  this->uninitialized_set(std::tuple<T...>(std::forward<A>(a)...));
347  }
348  template <typename... A>
349  void set(A&&... a) {
350  assert(_u.st == state::future);
351  new (this) future_state(ready_future_marker(), std::forward<A>(a)...);
352  }
353  future_state(exception_future_marker m, std::exception_ptr&& ex) : future_state_base(std::move(ex)) { }
354  std::tuple<T...> get_value() && noexcept {
355  assert(_u.st == state::result);
356  return std::move(this->uninitialized_get());
357  }
358  template<typename U = std::tuple<T...>>
359  std::enable_if_t<std::is_copy_constructible<U>::value, U> get_value() const& noexcept(copy_noexcept) {
360  assert(_u.st == state::result);
361  return this->uninitialized_get();
362  }
363  std::tuple<T...> get() && {
364  assert(_u.st != state::future);
365  if (_u.st >= state::exception_min) {
366  // Move ex out so future::~future() knows we've handled it
367  std::rethrow_exception(std::move(*this).get_exception());
368  }
369  return std::move(this->uninitialized_get());
370  }
371  std::tuple<T...> get() const& {
372  assert(_u.st != state::future);
373  if (_u.st >= state::exception_min) {
374  std::rethrow_exception(_u.ex);
375  }
376  return this->uninitialized_get();
377  }
378  void ignore() noexcept {
379  switch (_u.st) {
380  case state::invalid:
381  case state::future:
382  assert(0 && "invalid state for ignore");
383  case state::result:
384  this->~future_state();
385  break;
386  default:
387  // Ignore the exception
388  _u.take_exception();
389  }
390  _u.st = state::invalid;
391  }
392  using get0_return_type = typename internal::get0_return_type<T...>::type;
393  static get0_return_type get0(std::tuple<T...>&& x) {
394  return internal::get0_return_type<T...>::get0(std::move(x));
395  }
396 };
397 
398 static_assert(sizeof(future_state<>) <= 8, "future_state<> is too large");
399 static_assert(sizeof(future_state<long>) <= 16, "future_state<long> is too large");
400 
401 template <typename... T>
402 class continuation_base : public task {
403 protected:
404  future_state<T...> _state;
405  using future_type = future<T...>;
406  using promise_type = promise<T...>;
407 public:
408  continuation_base() = default;
409  explicit continuation_base(future_state<T...>&& state) : _state(std::move(state)) {}
410  void set_state(future_state<T...>&& state) {
411  _state = std::move(state);
412  }
413  friend class internal::promise_base_with_type<T...>;
414  friend class promise<T...>;
415  friend class future<T...>;
416 };
417 
418 template <typename Func, typename... T>
419 struct continuation final : continuation_base<T...> {
420  continuation(Func&& func, future_state<T...>&& state) : continuation_base<T...>(std::move(state)), _func(std::move(func)) {}
421  continuation(Func&& func) : _func(std::move(func)) {}
422  virtual void run_and_dispose() noexcept override {
423  _func(std::move(this->_state));
424  delete this;
425  }
426  Func _func;
427 };
428 
429 namespace internal {
430 
431 template <typename... T, typename U>
432 void set_callback(future<T...>& fut, std::unique_ptr<U> callback);
433 
434 class future_base;
435 
436 class promise_base {
437 protected:
438  enum class urgent { no, yes };
439  future_base* _future = nullptr;
440 
441  // This points to the future_state that is currently being
442  // used. See comment above the future_state struct definition for
443  // details.
444  future_state_base* _state;
445 
446  std::unique_ptr<task> _task;
447 
448  promise_base(const promise_base&) = delete;
449  promise_base(future_state_base* state) noexcept : _state(state) {}
450  promise_base(future_base* future, future_state_base* state) noexcept;
451  promise_base(promise_base&& x) noexcept;
452 
453  // We never need to destruct this polymorphicly, so we can make it
454  // protected instead of virtual
455  ~promise_base() noexcept;
456 
457  void operator=(const promise_base&) = delete;
458  promise_base& operator=(promise_base&& x) = delete;
459 
460  template<urgent Urgent>
461  __attribute__((always_inline))
462  void make_ready() noexcept;
463 
464  void set_exception(std::exception_ptr&& ex) noexcept {
465  if (_state) {
466  _state->set_exception(std::move(ex));
467  make_ready<urgent::no>();
468  } else {
469  // We get here if promise::get_future is called and the
470  // returned future is destroyed without creating a
471  // continuation.
472  // In older versions of seastar we would store a local
473  // copy of ex and warn in the promise destructor.
474  // Since there isn't any way for the user to clear
475  // the exception, we issue the warning from here.
476  report_failed_future(ex);
477  }
478  }
479 
480  void set_exception(const std::exception_ptr& ex) noexcept {
481  set_exception(std::exception_ptr(ex));
482  }
483 
484  template<typename Exception>
485  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
486  set_exception(make_exception_ptr(std::forward<Exception>(e)));
487  }
488 
489  friend class future_base;
490  template <typename... U> friend class seastar::future;
491 };
492 
499 template <typename... T>
500 class promise_base_with_type : protected internal::promise_base {
501 protected:
502  future_state<T...>* get_state() {
503  return static_cast<future_state<T...>*>(_state);
504  }
505  static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
506 public:
507  promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
508  promise_base_with_type(future<T...>* future) noexcept : promise_base(future, &future->_state) { }
509  promise_base_with_type(promise_base_with_type&& x) noexcept : promise_base(std::move(x)) { }
510  promise_base_with_type(const promise_base_with_type&) = delete;
511  promise_base_with_type& operator=(promise_base_with_type&& x) noexcept {
512  this->~promise_base_with_type();
513  new (this) promise_base_with_type(std::move(x));
514  return *this;
515  }
516  void operator=(const promise_base_with_type&) = delete;
517 
518  void set_urgent_state(future_state<T...>&& state) noexcept {
519  if (_state) {
520  *get_state() = std::move(state);
521  make_ready<urgent::yes>();
522  }
523  }
524 
525  template <typename... A>
526  void set_value(A&&... a) {
527  if (auto *s = get_state()) {
528  s->set(std::forward<A>(a)...);
529  make_ready<urgent::no>();
530  }
531  }
532 
533 #if SEASTAR_COROUTINES_TS
534  void set_coroutine(future_state<T...>& state, task& coroutine) noexcept {
535  _state = &state;
536  _task = std::unique_ptr<task>(&coroutine);
537  }
538 #endif
539 private:
540  template <typename Func>
541  void schedule(Func&& func) {
542  auto tws = std::make_unique<continuation<Func, T...>>(std::move(func));
543  _state = &tws->_state;
544  _task = std::move(tws);
545  }
546  void schedule(std::unique_ptr<continuation_base<T...>> callback) {
547  _state = &callback->_state;
548  _task = std::move(callback);
549  }
550 
551  template <typename... U>
552  friend class seastar::future;
553 
554  friend struct seastar::future_state<T...>;
555 };
556 }
558 
564 template <typename... T>
565 class promise : private internal::promise_base_with_type<T...> {
566  future_state<T...> _local_state;
567 
568 public:
572  promise() noexcept : internal::promise_base_with_type<T...>(&_local_state) {}
573 
575  promise(promise&& x) noexcept;
576  promise(const promise&) = delete;
577  promise& operator=(promise&& x) noexcept {
578  this->~promise();
579  new (this) promise(std::move(x));
580  return *this;
581  }
582  void operator=(const promise&) = delete;
583 
590  future<T...> get_future() noexcept;
591 
603  template <typename... A>
604  void set_value(A&&... a) {
605  internal::promise_base_with_type<T...>::set_value(std::forward<A>(a)...);
606  }
607 
612  void set_exception(std::exception_ptr&& ex) noexcept {
613  internal::promise_base::set_exception(std::move(ex));
614  }
615 
616  void set_exception(const std::exception_ptr& ex) noexcept {
617  internal::promise_base::set_exception(ex);
618  }
619 
624  template<typename Exception>
625  std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
626  internal::promise_base::set_exception(std::forward<Exception>(e));
627  }
628 
629  using internal::promise_base_with_type<T...>::set_urgent_state;
630 
631  template <typename... U>
632  friend class future;
633 };
634 
640 template<>
641 class promise<void> : public promise<> {};
642 
644 
647 
648 
654 template <typename... T> struct is_future : std::false_type {};
655 
658 template <typename... T> struct is_future<future<T...>> : std::true_type {};
659 
661 
662 
666 template <typename T>
667 struct futurize;
668 
669 template <typename T>
670 struct futurize {
672  using type = future<T>;
676  using value_type = std::tuple<T>;
677 
680  template<typename Func, typename... FuncArgs>
681  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
682 
685  template<typename Func, typename... FuncArgs>
686  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
687 
689  static inline type convert(T&& value) { return make_ready_future<T>(std::move(value)); }
690  static inline type convert(type&& value) { return std::move(value); }
691 
693  static type from_tuple(value_type&& value);
695  static type from_tuple(const value_type& value);
696 
698  template <typename Arg>
699  static type make_exception_future(Arg&& arg);
700 };
701 
703 template <>
704 struct futurize<void> {
705  using type = future<>;
706  using promise_type = promise<>;
707  using value_type = std::tuple<>;
708 
709  template<typename Func, typename... FuncArgs>
710  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
711 
712  template<typename Func, typename... FuncArgs>
713  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
714 
715  static inline type from_tuple(value_type&& value);
716  static inline type from_tuple(const value_type& value);
717 
718  template <typename Arg>
719  static type make_exception_future(Arg&& arg);
720 };
721 
722 template <typename... Args>
723 struct futurize<future<Args...>> {
724  using type = future<Args...>;
725  using promise_type = promise<Args...>;
726  using value_type = std::tuple<Args...>;
727 
728  template<typename Func, typename... FuncArgs>
729  static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
730 
731  template<typename Func, typename... FuncArgs>
732  static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
733 
734  static inline type from_tuple(value_type&& value);
735  static inline type from_tuple(const value_type& value);
736 
737  static inline type convert(Args&&... values) { return make_ready_future<Args...>(std::move(values)...); }
738  static inline type convert(type&& value) { return std::move(value); }
739 
740  template <typename Arg>
741  static type make_exception_future(Arg&& arg);
742 };
744 
745 // Converts a type to a future type, if it isn't already.
746 template <typename T>
747 using futurize_t = typename futurize<T>::type;
748 
750 
751 GCC6_CONCEPT(
752 
753 template <typename T>
754 concept bool Future = is_future<T>::value;
755 
756 template <typename Func, typename... T>
757 concept bool CanApply = requires (Func f, T... args) {
758  f(std::forward<T>(args)...);
759 };
760 
761 template <typename Func, typename Return, typename... T>
762 concept bool ApplyReturns = requires (Func f, T... args) {
763  { f(std::forward<T>(args)...) } -> Return;
764 };
765 
766 template <typename Func, typename... T>
767 concept bool ApplyReturnsAnyFuture = requires (Func f, T... args) {
768  requires is_future<decltype(f(std::forward<T>(args)...))>::value;
769 };
770 
771 )
772 
775 namespace internal {
776 class future_base {
777 protected:
778  promise_base* _promise;
779  future_base() noexcept : _promise(nullptr) {}
780  future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
781  _promise->_future = this;
782  _promise->_state = state;
783  }
784 
785  future_base(future_base&& x, future_state_base* state) noexcept : _promise(x._promise) {
786  if (auto* p = _promise) {
787  x.detach_promise();
788  p->_future = this;
789  p->_state = state;
790  }
791  }
792  ~future_base() noexcept {
793  if (_promise) {
794  detach_promise();
795  }
796  }
797 
798  promise_base* detach_promise() noexcept {
799  _promise->_state = nullptr;
800  _promise->_future = nullptr;
801  return std::exchange(_promise, nullptr);
802  }
803 
804  friend class promise_base;
805 };
806 
807 template <bool IsVariadic>
808 struct warn_variadic_future {
809  // Non-varidic case, do nothing
810  void check_deprecation() {}
811 };
812 
813 
814 // Note: placing the deprecated attribute on the class specialization has no effect.
815 template <>
816 struct warn_variadic_future<true> {
817  // Variadic case, has deprecation attribute
818  [[deprecated("Variadic future<> with more than one template parmeter is deprecated, replace with future<std::tuple<...>>")]]
819  void check_deprecation() {}
820 };
821 
822 }
823 
866 template <typename... T>
867 class SEASTAR_NODISCARD future : private internal::future_base, internal::warn_variadic_future<(sizeof...(T) > 1)> {
868  future_state<T...> _state;
869  static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
870 private:
871  // This constructor creates a future that is not ready but has no
872  // associated promise yet. The use case is to have a less flexible
873  // but more efficient future/promise pair where we know that
874  // promise::set_value cannot possibly be called without a matching
875  // future and so that promise doesn't need to store a
876  // future_state.
877  future(future_for_get_promise_marker m) { }
878 
879  future(promise<T...>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
880  template <typename... A>
881  future(ready_future_marker m, A&&... a) : _state(m, std::forward<A>(a)...) { }
882  future(exception_future_marker m, std::exception_ptr ex) noexcept : _state(m, std::move(ex)) { }
883  [[gnu::always_inline]]
884  explicit future(future_state<T...>&& state) noexcept
885  : _state(std::move(state)) {
886  this->check_deprecation();
887  }
888  internal::promise_base_with_type<T...> get_promise() noexcept {
889  assert(!_promise);
890  return internal::promise_base_with_type<T...>(this);
891  }
892  internal::promise_base_with_type<T...>* detach_promise() {
893  return static_cast<internal::promise_base_with_type<T...>*>(future_base::detach_promise());
894  }
895  template <typename Func>
896  void schedule(Func&& func) {
897  if (_state.available() || !_promise) {
898  if (__builtin_expect(!_state.available() && !_promise, false)) {
899  abandoned();
900  }
901  ::seastar::schedule(std::make_unique<continuation<Func, T...>>(std::move(func), std::move(_state)));
902  } else {
903  assert(_promise);
904  detach_promise()->schedule(std::move(func));
905  }
906  }
907 
908  [[gnu::always_inline]]
909  future_state<T...> get_available_state() noexcept {
910  if (_promise) {
911  detach_promise();
912  }
913  return std::move(_state);
914  }
915 
916  [[gnu::noinline]]
917  future<T...> rethrow_with_nested() {
918  if (!failed()) {
919  return make_exception_future<T...>(std::current_exception());
920  } else {
921  //
922  // Encapsulate the current exception into the
923  // std::nested_exception because the current libstdc++
924  // implementation has a bug requiring the value of a
925  // std::throw_with_nested() parameter to be of a polymorphic
926  // type.
927  //
928  std::nested_exception f_ex;
929  try {
930  get();
931  } catch (...) {
932  std::throw_with_nested(f_ex);
933  }
934  __builtin_unreachable();
935  }
936  }
937 
938  // Used when there is to attempt to attach a continuation or a thread to a future
939  // that was abandoned by its promise.
940  [[gnu::cold]] [[gnu::noinline]]
941  void abandoned() noexcept {
942  _state.set_to_broken_promise();
943  }
944 
945  template<typename... U>
946  friend class shared_future;
947 public:
949  using value_type = std::tuple<T...>;
951  using promise_type = promise<T...>;
953  [[gnu::always_inline]]
954  future(future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
955  future(const future&) = delete;
956  future& operator=(future&& x) noexcept {
957  this->~future();
958  new (this) future(std::move(x));
959  return *this;
960  }
961  void operator=(const future&) = delete;
971  [[gnu::always_inline]]
972  std::tuple<T...> get() {
973  if (!_state.available()) {
974  do_wait();
975  }
976  return get_available_state().get();
977  }
978 
979  [[gnu::always_inline]]
980  std::exception_ptr get_exception() {
981  return get_available_state().get_exception();
982  }
983 
992  typename future_state<T...>::get0_return_type get0() {
993  return future_state<T...>::get0(get());
994  }
995 
1001  void wait() noexcept {
1002  if (!_state.available()) {
1003  do_wait();
1004  }
1005  }
1006 private:
1007  class thread_wake_task final : public continuation_base<T...> {
1008  thread_context* _thread;
1009  future* _waiting_for;
1010  public:
1011  thread_wake_task(thread_context* thread, future* waiting_for)
1012  : _thread(thread), _waiting_for(waiting_for) {
1013  }
1014  virtual void run_and_dispose() noexcept override {
1015  _waiting_for->_state = std::move(this->_state);
1016  thread_impl::switch_in(_thread);
1017  // no need to delete, since this is always allocated on
1018  // _thread's stack.
1019  }
1020  };
1021  void do_wait() noexcept {
1022  if (__builtin_expect(!_promise, false)) {
1023  abandoned();
1024  return;
1025  }
1026  auto thread = thread_impl::get();
1027  assert(thread);
1028  thread_wake_task wake_task{thread, this};
1029  detach_promise()->schedule(std::unique_ptr<continuation_base<T...>>(&wake_task));
1030  thread_impl::switch_out(thread);
1031  }
1032 
1033 public:
1037  [[gnu::always_inline]]
1038  bool available() const noexcept {
1039  return _state.available();
1040  }
1041 
1045  [[gnu::always_inline]]
1046  bool failed() const noexcept {
1047  return _state.failed();
1048  }
1049 
1065  template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1066  GCC6_CONCEPT( requires ::seastar::CanApply<Func, T...> )
1067  Result
1068  then(Func&& func) noexcept {
1069 #ifndef SEASTAR_TYPE_ERASE_MORE
1070  return then_impl(std::move(func));
1071 #else
1072  using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1073  return then_impl(noncopyable_function<Result (T&&...)>([func = std::forward<Func>(func)] (T&&... args) mutable {
1074  return futurator::apply(func, std::forward_as_tuple(std::move(args)...));
1075  }));
1076 #endif
1077  }
1078 
1079 private:
1080 
1081  template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1082  Result
1083  then_impl(Func&& func) noexcept {
1084  using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1085  if (available() && !need_preempt()) {
1086  if (failed()) {
1087  return futurator::make_exception_future(get_available_state().get_exception());
1088  } else {
1089  return futurator::apply(std::forward<Func>(func), get_available_state().get_value());
1090  }
1091  }
1092  typename futurator::type fut(future_for_get_promise_marker{});
1093  // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1094  // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1095  // that happens.
1096  [&] () noexcept {
1097  memory::disable_failure_guard dfg;
1098  schedule([pr = fut.get_promise(), func = std::forward<Func>(func)] (future_state<T...>&& state) mutable {
1099  if (state.failed()) {
1100  pr.set_exception(std::move(state).get_exception());
1101  } else {
1102  futurator::apply(std::forward<Func>(func), std::move(state).get_value()).forward_to(std::move(pr));
1103  }
1104  });
1105  } ();
1106  return fut;
1107  }
1108 
1109 public:
1125  template <typename Func, typename Result = futurize_t<std::result_of_t<Func(future)>>>
1126  GCC6_CONCEPT( requires ::seastar::CanApply<Func, future> )
1127  Result
1128  then_wrapped(Func&& func) noexcept {
1129 #ifndef SEASTAR_TYPE_ERASE_MORE
1130  return then_wrapped_impl(std::move(func));
1131 #else
1132  using futurator = futurize<std::result_of_t<Func(future)>>;
1133  return then_wrapped_impl(noncopyable_function<Result (future)>([func = std::forward<Func>(func)] (future f) mutable {
1134  return futurator::apply(std::forward<Func>(func), std::move(f));
1135  }));
1136 #endif
1137  }
1138 
1139 private:
1140 
1141  template <typename Func, typename Result = futurize_t<std::result_of_t<Func(future)>>>
1142  Result
1143  then_wrapped_impl(Func&& func) noexcept {
1144  using futurator = futurize<std::result_of_t<Func(future)>>;
1145  if (available() && !need_preempt()) {
1146  return futurator::apply(std::forward<Func>(func), future(get_available_state()));
1147  }
1148  typename futurator::type fut(future_for_get_promise_marker{});
1149  // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1150  // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1151  // that happens.
1152  [&] () noexcept {
1153  memory::disable_failure_guard dfg;
1154  schedule([pr = fut.get_promise(), func = std::forward<Func>(func)] (future_state<T...>&& state) mutable {
1155  futurator::apply(std::forward<Func>(func), future(std::move(state))).forward_to(std::move(pr));
1156  });
1157  } ();
1158  return fut;
1159  }
1160 
1161  void forward_to(internal::promise_base_with_type<T...>&& pr) noexcept {
1162  if (_state.available()) {
1163  pr.set_urgent_state(std::move(_state));
1164  } else {
1165  *detach_promise() = std::move(pr);
1166  }
1167  }
1168 
1169 public:
1180  void forward_to(promise<T...>&& pr) noexcept {
1181  if (_state.available()) {
1182  pr.set_urgent_state(std::move(_state));
1183  } else if (&pr._local_state != pr._state) {
1184  // The only case when _state points to _local_state is
1185  // when get_future was never called. Given that pr will
1186  // soon be destroyed, we know get_future will never be
1187  // called and we can just ignore this request.
1188  *detach_promise() = std::move(pr);
1189  }
1190  }
1191 
1192 
1193 
1209  template <typename Func>
1210  GCC6_CONCEPT( requires ::seastar::CanApply<Func> )
1211  future<T...> finally(Func&& func) noexcept {
1212  return then_wrapped(finally_body<Func, is_future<std::result_of_t<Func()>>::value>(std::forward<Func>(func)));
1213  }
1214 
1215 
1216  template <typename Func, bool FuncReturnsFuture>
1218 
1219  template <typename Func>
1220  struct finally_body<Func, true> {
1221  Func _func;
1222 
1223  finally_body(Func&& func) : _func(std::forward<Func>(func))
1224  { }
1225 
1226  future<T...> operator()(future<T...>&& result) {
1227  using futurator = futurize<std::result_of_t<Func()>>;
1228  return futurator::apply(_func).then_wrapped([result = std::move(result)](auto f_res) mutable {
1229  if (!f_res.failed()) {
1230  return std::move(result);
1231  } else {
1232  try {
1233  f_res.get();
1234  } catch (...) {
1235  return result.rethrow_with_nested();
1236  }
1237  __builtin_unreachable();
1238  }
1239  });
1240  }
1241  };
1242 
1243  template <typename Func>
1244  struct finally_body<Func, false> {
1245  Func _func;
1246 
1247  finally_body(Func&& func) : _func(std::forward<Func>(func))
1248  { }
1249 
1250  future<T...> operator()(future<T...>&& result) {
1251  try {
1252  _func();
1253  return std::move(result);
1254  } catch (...) {
1255  return result.rethrow_with_nested();
1256  }
1257  };
1258  };
1259 
1264  future<> or_terminate() noexcept {
1265  return then_wrapped([] (auto&& f) {
1266  try {
1267  f.get();
1268  } catch (...) {
1269  engine_exit(std::current_exception());
1270  }
1271  });
1272  }
1273 
1279  return then([] (T&&...) {});
1280  }
1281 
1295  template <typename Func>
1296  /* Broken?
1297  GCC6_CONCEPT( requires ::seastar::ApplyReturns<Func, future<T...>, std::exception_ptr>
1298  || (sizeof...(T) == 0 && ::seastar::ApplyReturns<Func, void, std::exception_ptr>)
1299  || (sizeof...(T) == 1 && ::seastar::ApplyReturns<Func, T..., std::exception_ptr>)
1300  ) */
1301  future<T...> handle_exception(Func&& func) noexcept {
1302  using func_ret = std::result_of_t<Func(std::exception_ptr)>;
1303  return then_wrapped([func = std::forward<Func>(func)]
1304  (auto&& fut) mutable -> future<T...> {
1305  if (!fut.failed()) {
1306  return make_ready_future<T...>(fut.get());
1307  } else {
1308  return futurize<func_ret>::apply(func, fut.get_exception());
1309  }
1310  });
1311  }
1312 
1323  template <typename Func>
1324  future<T...> handle_exception_type(Func&& func) noexcept {
1325  using trait = function_traits<Func>;
1326  static_assert(trait::arity == 1, "func can take only one parameter");
1327  using ex_type = typename trait::template arg<0>::type;
1328  using func_ret = typename trait::return_type;
1329  return then_wrapped([func = std::forward<Func>(func)]
1330  (auto&& fut) mutable -> future<T...> {
1331  try {
1332  return make_ready_future<T...>(fut.get());
1333  } catch(ex_type& ex) {
1334  return futurize<func_ret>::apply(func, ex);
1335  }
1336  });
1337  }
1338 
1344  void ignore_ready_future() noexcept {
1345  _state.ignore();
1346  }
1347 
1348 #if SEASTAR_COROUTINES_TS
1349  void set_coroutine(task& coroutine) noexcept {
1350  assert(!_state.available());
1351  assert(_promise);
1352  detach_promise()->set_coroutine(_state, coroutine);
1353  }
1354 #endif
1355 private:
1356  void set_callback(std::unique_ptr<continuation_base<T...>> callback) {
1357  if (_state.available()) {
1358  callback->set_state(get_available_state());
1359  ::seastar::schedule(std::move(callback));
1360  } else {
1361  assert(_promise);
1362  detach_promise()->schedule(std::move(callback));
1363  }
1364 
1365  }
1366 
1368  template <typename... U>
1369  friend class future;
1370  template <typename... U>
1371  friend class promise;
1372  template <typename... U>
1373  friend class internal::promise_base_with_type;
1374  template <typename... U, typename... A>
1375  friend future<U...> make_ready_future(A&&... value);
1376  template <typename... U>
1377  friend future<U...> make_exception_future(std::exception_ptr ex) noexcept;
1378  template <typename... U, typename Exception>
1379  friend future<U...> make_exception_future(Exception&& ex) noexcept;
1380  template <typename... U, typename V>
1381  friend void internal::set_callback(future<U...>&, std::unique_ptr<V>);
1383 };
1384 
1385 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1386  : _future(future), _state(state) {
1387  _future->_promise = this;
1388 }
1389 
1390 template <typename... T>
1391 inline
1392 future<T...>
1394  assert(!this->_future && this->_state && !this->_task);
1395  return future<T...>(this);
1396 }
1397 
1398 template<internal::promise_base::urgent Urgent>
1399 inline
1400 void internal::promise_base::make_ready() noexcept {
1401  if (_task) {
1402  _state = nullptr;
1403  if (Urgent == urgent::yes && !need_preempt()) {
1404  ::seastar::schedule_urgent(std::move(_task));
1405  } else {
1406  ::seastar::schedule(std::move(_task));
1407  }
1408  }
1409 }
1410 
1411 template <typename... T>
1412 inline
1413 promise<T...>::promise(promise&& x) noexcept : internal::promise_base_with_type<T...>(std::move(x)) {
1414  if (this->_state == &x._local_state) {
1415  this->_state = &_local_state;
1416  _local_state = std::move(x._local_state);
1417  }
1418 }
1419 
1420 template <typename... T, typename... A>
1421 inline
1422 future<T...> make_ready_future(A&&... value) {
1423  return future<T...>(ready_future_marker(), std::forward<A>(value)...);
1424 }
1425 
1426 template <typename... T>
1427 inline
1428 future<T...> make_exception_future(std::exception_ptr ex) noexcept {
1429  return future<T...>(exception_future_marker(), std::move(ex));
1430 }
1431 
1432 void log_exception_trace() noexcept;
1433 
1440 template <typename... T, typename Exception>
1441 inline
1442 future<T...> make_exception_future(Exception&& ex) noexcept {
1443  log_exception_trace();
1444  return make_exception_future<T...>(std::make_exception_ptr(std::forward<Exception>(ex)));
1445 }
1446 
1448 
1450 
1451 template<typename T>
1452 template<typename Func, typename... FuncArgs>
1453 typename futurize<T>::type futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1454  try {
1455  return convert(::seastar::apply(std::forward<Func>(func), std::move(args)));
1456  } catch (...) {
1457  return make_exception_future(std::current_exception());
1458  }
1459 }
1460 
1461 template<typename T>
1462 template<typename Func, typename... FuncArgs>
1463 typename futurize<T>::type futurize<T>::apply(Func&& func, FuncArgs&&... args) noexcept {
1464  try {
1465  return convert(func(std::forward<FuncArgs>(args)...));
1466  } catch (...) {
1467  return make_exception_future(std::current_exception());
1468  }
1469 }
1470 
1471 template <typename Ret> // Ret = void | future<>
1472 struct do_void_futurize_helper;
1473 
1474 template <>
1475 struct do_void_futurize_helper<void> {
1476  template <typename Func, typename... FuncArgs>
1477  static future<> apply(Func&& func, FuncArgs&&... args) noexcept {
1478  try {
1479  func(std::forward<FuncArgs>(args)...);
1480  return make_ready_future<>();
1481  } catch (...) {
1482  return make_exception_future(std::current_exception());
1483  }
1484  }
1485 
1486  template<typename Func, typename... FuncArgs>
1487  static future<> apply_tuple(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1488  try {
1489  ::seastar::apply(std::forward<Func>(func), std::move(args));
1490  return make_ready_future<>();
1491  } catch (...) {
1492  return make_exception_future(std::current_exception());
1493  }
1494  }
1495 };
1496 
1497 template <>
1498 struct do_void_futurize_helper<future<>> {
1499  template <typename Func, typename... FuncArgs>
1500  static future<> apply(Func&& func, FuncArgs&&... args) noexcept {
1501  try {
1502  return func(std::forward<FuncArgs>(args)...);
1503  } catch (...) {
1504  return make_exception_future(std::current_exception());
1505  }
1506  }
1507 
1508  template<typename Func, typename... FuncArgs>
1509  static future<> apply_tuple(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1510  try {
1511  return ::seastar::apply(std::forward<Func>(func), std::move(args));
1512  } catch (...) {
1513  return make_exception_future(std::current_exception());
1514  }
1515  }
1516 };
1517 
1518 template <typename Func, typename... FuncArgs>
1519 using void_futurize_helper = do_void_futurize_helper<std::result_of_t<Func(FuncArgs&&...)>>;
1520 
1521 template<typename Func, typename... FuncArgs>
1522 typename futurize<void>::type futurize<void>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1523  return void_futurize_helper<Func, FuncArgs...>::apply_tuple(std::forward<Func>(func), std::move(args));
1524 }
1525 
1526 template<typename Func, typename... FuncArgs>
1527 typename futurize<void>::type futurize<void>::apply(Func&& func, FuncArgs&&... args) noexcept {
1528  return void_futurize_helper<Func, FuncArgs...>::apply(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1529 }
1530 
1531 template<typename... Args>
1532 template<typename Func, typename... FuncArgs>
1533 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1534  try {
1535  return ::seastar::apply(std::forward<Func>(func), std::move(args));
1536  } catch (...) {
1537  return make_exception_future(std::current_exception());
1538  }
1539 }
1540 
1541 template<typename... Args>
1542 template<typename Func, typename... FuncArgs>
1543 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, FuncArgs&&... args) noexcept {
1544  try {
1545  return func(std::forward<FuncArgs>(args)...);
1546  } catch (...) {
1547  return make_exception_future(std::current_exception());
1548  }
1549 }
1550 
1551 template <typename T>
1552 template <typename Arg>
1553 inline
1554 future<T>
1556  return ::seastar::make_exception_future<T>(std::forward<Arg>(arg));
1557 }
1558 
1559 template <typename... T>
1560 template <typename Arg>
1561 inline
1562 future<T...>
1563 futurize<future<T...>>::make_exception_future(Arg&& arg) {
1564  return ::seastar::make_exception_future<T...>(std::forward<Arg>(arg));
1565 }
1566 
1567 template <typename Arg>
1568 inline
1569 future<>
1571  return ::seastar::make_exception_future<>(std::forward<Arg>(arg));
1572 }
1573 
1574 template <typename T>
1575 inline
1576 future<T>
1577 futurize<T>::from_tuple(std::tuple<T>&& value) {
1578  return make_ready_future<T>(std::move(value));
1579 }
1580 
1581 template <typename T>
1582 inline
1583 future<T>
1584 futurize<T>::from_tuple(const std::tuple<T>& value) {
1585  return make_ready_future<T>(value);
1586 }
1587 
1588 inline
1589 future<>
1590 futurize<void>::from_tuple(std::tuple<>&& value) {
1591  return make_ready_future<>();
1592 }
1593 
1594 inline
1595 future<>
1596 futurize<void>::from_tuple(const std::tuple<>& value) {
1597  return make_ready_future<>();
1598 }
1599 
1600 template <typename... Args>
1601 inline
1602 future<Args...>
1603 futurize<future<Args...>>::from_tuple(std::tuple<Args...>&& value) {
1604  return make_ready_future<Args...>(std::move(value));
1605 }
1606 
1607 template <typename... Args>
1608 inline
1609 future<Args...>
1610 futurize<future<Args...>>::from_tuple(const std::tuple<Args...>& value) {
1611  return make_ready_future<Args...>(value);
1612 }
1613 
1614 template<typename Func, typename... Args>
1615 auto futurize_apply(Func&& func, Args&&... args) {
1616  using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
1617  return futurator::apply(std::forward<Func>(func), std::forward<Args>(args)...);
1618 }
1619 
1620 namespace internal {
1621 
1622 template <typename... T, typename U>
1623 inline
1624 void set_callback(future<T...>& fut, std::unique_ptr<U> callback) {
1625  // It would be better to use continuation_base<T...> for U, but
1626  // then a derived class of continuation_base<T...> won't be matched
1627  return fut.set_callback(std::move(callback));
1628 }
1629 
1630 }
1631 
1632 
1634 
1635 }
future< T... > handle_exception_type(Func &&func) noexcept
Handle the exception of a certain type carried by this future.
Definition: future.hh:1324
future< T... > make_ready_future(A &&... value)
Creates a future in an available, value state.
Definition: future.hh:1422
Definition: noncopyable_function.hh:31
Definition: future.hh:313
A representation of a possibly not-yet-computed value.
Definition: future.hh:79
void wait() noexcept
Definition: future.hh:1001
static type make_exception_future(Arg &&arg)
Makes an exceptional future of type type.
void set_exception(std::exception_ptr &&ex) noexcept
Marks the promise as failed.
Definition: future.hh:612
promise() noexcept
Constructs an empty promise.
Definition: future.hh:572
Definition: future.hh:240
Check whether a type is a future.
Definition: future.hh:654
bool failed() const noexcept
Checks whether the future has failed.
Definition: future.hh:1046
STL namespace.
static type apply(Func &&func, std::tuple< FuncArgs... > &&args) noexcept
thread - stateful thread of execution
Definition: thread.hh:153
Exception type for broken promises.
Definition: future.hh:114
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:667
void forward_to(promise< T... > &&pr) noexcept
Satisfy some promise object with this future as a result.
Definition: future.hh:1180
Result then_wrapped(Func &&func) noexcept
Schedule a block of code to run when the future is ready, allowing for exception handling.
Definition: future.hh:1128
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:676
promise< T > promise_type
The promise type associated with type.
Definition: future.hh:674
bool available() const noexcept
Checks whether the future is available.
Definition: future.hh:1038
future< T... > handle_exception(Func &&func) noexcept
Handle the exception carried by this future.
Definition: future.hh:1301
future_state< T... >::get0_return_type get0()
Definition: future.hh:992
Definition: future.hh:1217
void set_value(A &&... a)
Sets the promises value.
Definition: future.hh:604
static type convert(T &&value)
Convert a value or a future to a future.
Definition: future.hh:689
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:1068
future< T... > make_exception_future(std::exception_ptr value) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1428
future< T > type
If T is a future, T; otherwise future<T>
Definition: future.hh:672
Definition: future.hh:228
future< T... > get_future() noexcept
Gets the promise&#39;s associated future.
Definition: future.hh:1393
Definition: task.hh:29
Definition: future.hh:314
future< T... > make_exception_future(Exception &&ex) noexcept
Creates a future in an available, failed state.
Definition: future.hh:1442
future(future &&x) noexcept
Moves the future into a new object.
Definition: future.hh:954
std::tuple< T... > value_type
The data type carried by the future.
Definition: future.hh:949
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:1264
future discard_result() noexcept
Discards the value carried by this future.
Definition: future.hh:1278
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:625
Seastar API namespace.
Definition: abort_on_ebadf.hh:24
void ignore_ready_future() noexcept
Ignore any result hold by this future.
Definition: future.hh:1344