]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/include/seastar/core/future.hh
import 15.2.0 Octopus source
[ceph.git] / ceph / src / seastar / include / seastar / core / 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
42 /// \defgroup future-module Futures and Promises
43 ///
44 /// \brief
45 /// Futures and promises are the basic tools for asynchronous
46 /// programming in seastar. A future represents a result that
47 /// may not have been computed yet, for example a buffer that
48 /// is being read from the disk, or the result of a function
49 /// that is executed on another cpu. A promise object allows
50 /// the future to be eventually resolved by assigning it a value.
51 ///
52 /// \brief
53 /// Another way to look at futures and promises are as the reader
54 /// and writer sides, respectively, of a single-item, single use
55 /// queue. You read from the future, and write to the promise,
56 /// and the system takes care that it works no matter what the
57 /// order of operations is.
58 ///
59 /// \brief
60 /// The normal way of working with futures is to chain continuations
61 /// to them. A continuation is a block of code (usually a lamdba)
62 /// that is called when the future is assigned a value (the future
63 /// is resolved); the continuation can then access the actual value.
64 ///
65
66 /// \defgroup future-util Future Utilities
67 ///
68 /// \brief
69 /// These utilities are provided to help perform operations on futures.
70
71
72 /// \addtogroup future-module
73 /// @{
74
75 template <class... T>
76 class promise;
77
78 template <class... T>
79 class future;
80
81 template <typename... T>
82 class shared_future;
83
84 struct future_state_base;
85
86 /// \brief Creates a \ref future in an available, value state.
87 ///
88 /// Creates a \ref future object that is already resolved. This
89 /// is useful when it is determined that no I/O needs to be performed
90 /// to perform a computation (for example, because the data is cached
91 /// in some buffer).
92 template <typename... T, typename... A>
93 future<T...> make_ready_future(A&&... value);
94
95 /// \brief Creates a \ref future in an available, failed state.
96 ///
97 /// Creates a \ref future object that is already resolved in a failed
98 /// state. This is useful when no I/O needs to be performed to perform
99 /// a computation (for example, because the connection is closed and
100 /// we cannot read from it).
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
114 /// \cond internal
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
121 /// \endcond
122
123 /// \brief Exception type for broken promises
124 ///
125 /// When a promise is broken, i.e. a promise object with an attached
126 /// continuation is destroyed before setting any value or exception, an
127 /// exception of `broken_promise` type is propagated to that abandoned
128 /// continuation.
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
157 /// \brief Wrapper for keeping uninitialized values of non default constructible types.
158 ///
159 /// This is similar to a std::optional<T>, but it doesn't know if it is holding a value or not, so the user is
160 /// responsible for calling constructors and destructors.
161 ///
162 /// The advantage over just using a union directly is that this uses inheritance when possible and so benefits from the
163 /// empty base optimization.
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 void uninitialized_set(T&& v) {
177 new (&_v.value) T(std::move(v));
178 }
179 T& uninitialized_get() {
180 return _v.value;
181 }
182 const T& uninitialized_get() const {
183 return _v.value;
184 }
185 };
186
187 template <typename T> struct uninitialized_wrapper_base<T, true> : private T {
188 void uninitialized_set(T&& v) {
189 new (this) T(std::move(v));
190 }
191 T& uninitialized_get() {
192 return *this;
193 }
194 const T& uninitialized_get() const {
195 return *this;
196 }
197 };
198
199 template <typename T>
200 constexpr bool can_inherit =
201 #ifdef _LIBCPP_VERSION
202 // We expect std::tuple<> to be trivially constructible and
203 // destructible. That is not the case with libc++
204 // (https://bugs.llvm.org/show_bug.cgi?id=41714). We could avoid this
205 // optimization when using libc++ and relax the asserts, but
206 // inspection suggests that std::tuple<> is trivial, it is just not
207 // marked as such.
208 std::is_same<std::tuple<>, T>::value ||
209 #endif
210 (std::is_trivially_destructible<T>::value && std::is_trivially_constructible<T>::value &&
211 std::is_class<T>::value && !std::is_final<T>::value);
212
213 // The objective is to avoid extra space for empty types like std::tuple<>. We could use std::is_empty_v, but it is
214 // better to check that both the constructor and destructor can be skipped.
215 template <typename T>
216 struct uninitialized_wrapper
217 : public uninitialized_wrapper_base<T, can_inherit<T>> {};
218
219 static_assert(std::is_empty<uninitialized_wrapper<std::tuple<>>>::value, "This should still be empty");
220
221 template <typename T>
222 struct is_trivially_move_constructible_and_destructible {
223 static constexpr bool value = std::is_trivially_move_constructible<T>::value && std::is_trivially_destructible<T>::value;
224 };
225
226 template <bool... v>
227 struct all_true : std::false_type {};
228
229 template <>
230 struct all_true<> : std::true_type {};
231
232 template <bool... v>
233 struct all_true<true, v...> : public all_true<v...> {};
234 }
235
236 //
237 // A future/promise pair maintain one logical value (a future_state).
238 // There are up to three places that can store it, but only one is
239 // active at any time.
240 //
241 // - in the promise _local_state member variable
242 //
243 // This is necessary because a promise is created first and there
244 // would be nowhere else to put the value.
245 //
246 // - in the future _state variable
247 //
248 // This is used anytime a future exists and then has not been called
249 // yet. This guarantees a simple access to the value for any code
250 // that already has a future.
251 //
252 // - in the task associated with the .then() clause (after .then() is called,
253 // if a value was not set)
254 //
255 //
256 // The promise maintains a pointer to the state, which is modified as
257 // the state moves to a new location due to events (such as .then() or
258 // get_future being called) or due to the promise or future being
259 // moved around.
260 //
261
262 // non templated base class to reduce code duplication
263 struct future_state_base {
264 static_assert(std::is_nothrow_copy_constructible<std::exception_ptr>::value,
265 "std::exception_ptr's copy constructor must not throw");
266 static_assert(std::is_nothrow_move_constructible<std::exception_ptr>::value,
267 "std::exception_ptr's move constructor must not throw");
268 static_assert(sizeof(std::exception_ptr) == sizeof(void*), "exception_ptr not a pointer");
269 enum class state : uintptr_t {
270 invalid = 0,
271 future = 1,
272 // the substate is intended to decouple the run-time prevention
273 // for duplicative result extraction (calling e.g. then() twice
274 // ends up in abandoned()) from the wrapped object's destruction
275 // handling which is orchestrated by future_state. Instead of
276 // creating a temporary future_state just for the sake of setting
277 // the "invalid" in the source instance, result_unavailable can
278 // be set to ensure future_state_base::available() returns false.
279 result_unavailable = 2,
280 result = 3,
281 exception_min = 4, // or anything greater
282 };
283 union any {
284 any() { st = state::future; }
285 any(state s) { st = s; }
286 void set_exception(std::exception_ptr&& e) {
287 new (&ex) std::exception_ptr(std::move(e));
288 assert(st >= state::exception_min);
289 }
290 any(std::exception_ptr&& e) {
291 set_exception(std::move(e));
292 }
293 ~any() {}
294 std::exception_ptr take_exception() {
295 std::exception_ptr ret(std::move(ex));
296 // Unfortunately in libstdc++ ~exception_ptr is defined out of line. We know that it does nothing for
297 // moved out values, so we omit calling it. This is critical for the code quality produced for this
298 // function. Without the out of line call, gcc can figure out that both sides of the if produce
299 // identical code and merges them.if
300 // We don't make any assumptions about other c++ libraries.
301 // There is request with gcc to define it inline: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90295
302 #ifndef __GLIBCXX__
303 ex.~exception_ptr();
304 #endif
305 st = state::invalid;
306 return ret;
307 }
308 any(any&& x) {
309 if (x.st < state::exception_min) {
310 st = x.st;
311 x.st = state::invalid;
312 } else {
313 new (&ex) std::exception_ptr(x.take_exception());
314 }
315 }
316 bool has_result() const {
317 return st == state::result || st == state::result_unavailable;
318 }
319 state st;
320 std::exception_ptr ex;
321 } _u;
322
323 future_state_base() noexcept { }
324 future_state_base(state st) noexcept : _u(st) { }
325 future_state_base(std::exception_ptr&& ex) noexcept : _u(std::move(ex)) { }
326 future_state_base(future_state_base&& x) noexcept : _u(std::move(x._u)) { }
327
328 // We never need to destruct this polymorphicly, so we can make it
329 // protected instead of virtual.
330 protected:
331 ~future_state_base() noexcept {
332 if (failed()) {
333 report_failed_future(_u.take_exception());
334 }
335 }
336
337 public:
338
339 bool valid() const noexcept { return _u.st != state::invalid; }
340 bool available() const noexcept { return _u.st == state::result || _u.st >= state::exception_min; }
341 bool failed() const noexcept { return __builtin_expect(_u.st >= state::exception_min, false); }
342
343 void set_to_broken_promise() noexcept;
344
345 void ignore() noexcept {
346 switch (_u.st) {
347 case state::invalid:
348 case state::future:
349 assert(0 && "invalid state for ignore");
350 case state::result_unavailable:
351 case state::result:
352 _u.st = state::result_unavailable;
353 break;
354 default:
355 // Ignore the exception
356 _u.take_exception();
357 }
358 }
359
360 void set_exception(std::exception_ptr&& ex) noexcept {
361 assert(_u.st == state::future);
362 _u.set_exception(std::move(ex));
363 }
364 future_state_base& operator=(future_state_base&& x) noexcept {
365 this->~future_state_base();
366 new (this) future_state_base(std::move(x));
367 return *this;
368 }
369 void set_exception(future_state_base&& state) noexcept {
370 assert(_u.st == state::future);
371 *this = std::move(state);
372 }
373 std::exception_ptr get_exception() && noexcept {
374 assert(_u.st >= state::exception_min);
375 // Move ex out so future::~future() knows we've handled it
376 return _u.take_exception();
377 }
378 const std::exception_ptr& get_exception() const& noexcept {
379 assert(_u.st >= state::exception_min);
380 return _u.ex;
381 }
382
383 static future_state_base current_exception();
384
385 template <typename... U>
386 friend future<U...> internal::current_exception_as_future() noexcept;
387 };
388
389 struct ready_future_marker {};
390 struct exception_future_marker {};
391 struct future_for_get_promise_marker {};
392
393 /// \cond internal
394 template <typename... T>
395 struct future_state : public future_state_base, private internal::uninitialized_wrapper<std::tuple<T...>> {
396 static constexpr bool copy_noexcept = std::is_nothrow_copy_constructible<std::tuple<T...>>::value;
397 static constexpr bool has_trivial_move_and_destroy =
398 internal::all_true<internal::is_trivially_move_constructible_and_destructible<T>::value...>::value;
399 static_assert(std::is_nothrow_move_constructible<std::tuple<T...>>::value,
400 "Types must be no-throw move constructible");
401 static_assert(std::is_nothrow_destructible<std::tuple<T...>>::value,
402 "Types must be no-throw destructible");
403 future_state() noexcept {}
404 [[gnu::always_inline]]
405 future_state(future_state&& x) noexcept : future_state_base(std::move(x)) {
406 if (has_trivial_move_and_destroy) {
407 memcpy(reinterpret_cast<char*>(&this->uninitialized_get()),
408 &x.uninitialized_get(),
409 internal::used_size<std::tuple<T...>>::value);
410 } else if (_u.has_result()) {
411 this->uninitialized_set(std::move(x.uninitialized_get()));
412 x.uninitialized_get().~tuple();
413 }
414 }
415 __attribute__((always_inline))
416 ~future_state() noexcept {
417 if (_u.has_result()) {
418 this->uninitialized_get().~tuple();
419 }
420 }
421 future_state& operator=(future_state&& x) noexcept {
422 this->~future_state();
423 new (this) future_state(std::move(x));
424 return *this;
425 }
426 template <typename... A>
427 future_state(ready_future_marker, A&&... a) : future_state_base(state::result) {
428 this->uninitialized_set(std::tuple<T...>(std::forward<A>(a)...));
429 }
430 template <typename... A>
431 void set(A&&... a) {
432 assert(_u.st == state::future);
433 new (this) future_state(ready_future_marker(), std::forward<A>(a)...);
434 }
435 future_state(exception_future_marker m, std::exception_ptr&& ex) : future_state_base(std::move(ex)) { }
436 future_state(exception_future_marker m, future_state_base&& state) : future_state_base(std::move(state)) { }
437 std::tuple<T...>&& get_value() && noexcept {
438 assert(_u.st == state::result);
439 return std::move(this->uninitialized_get());
440 }
441 std::tuple<T...>&& take_value() && noexcept {
442 assert(_u.st == state::result);
443 _u.st = state::result_unavailable;
444 return std::move(this->uninitialized_get());
445 }
446 template<typename U = std::tuple<T...>>
447 const std::enable_if_t<std::is_copy_constructible<U>::value, U>& get_value() const& noexcept(copy_noexcept) {
448 assert(_u.st == state::result);
449 return this->uninitialized_get();
450 }
451 std::tuple<T...>&& take() && {
452 assert(available());
453 if (_u.st >= state::exception_min) {
454 // Move ex out so future::~future() knows we've handled it
455 std::rethrow_exception(std::move(*this).get_exception());
456 }
457 _u.st = state::result_unavailable;
458 return std::move(this->uninitialized_get());
459 }
460 std::tuple<T...>&& get() && {
461 assert(available());
462 if (_u.st >= state::exception_min) {
463 // Move ex out so future::~future() knows we've handled it
464 std::rethrow_exception(std::move(*this).get_exception());
465 }
466 return std::move(this->uninitialized_get());
467 }
468 const std::tuple<T...>& get() const& {
469 assert(available());
470 if (_u.st >= state::exception_min) {
471 std::rethrow_exception(_u.ex);
472 }
473 return this->uninitialized_get();
474 }
475 using get0_return_type = typename internal::get0_return_type<T...>::type;
476 static get0_return_type get0(std::tuple<T...>&& x) {
477 return internal::get0_return_type<T...>::get0(std::move(x));
478 }
479 };
480
481 static_assert(sizeof(future_state<>) <= 8, "future_state<> is too large");
482 static_assert(sizeof(future_state<long>) <= 16, "future_state<long> is too large");
483
484 template <typename... T>
485 class continuation_base : public task {
486 protected:
487 future_state<T...> _state;
488 using future_type = future<T...>;
489 using promise_type = promise<T...>;
490 public:
491 continuation_base() = default;
492 explicit continuation_base(future_state<T...>&& state) : _state(std::move(state)) {}
493 void set_state(future_state<T...>&& state) {
494 _state = std::move(state);
495 }
496 friend class internal::promise_base_with_type<T...>;
497 friend class promise<T...>;
498 friend class future<T...>;
499 };
500
501 template <typename Func, typename... T>
502 struct continuation final : continuation_base<T...> {
503 continuation(Func&& func, future_state<T...>&& state) : continuation_base<T...>(std::move(state)), _func(std::move(func)) {}
504 continuation(Func&& func) : _func(std::move(func)) {}
505 virtual void run_and_dispose() noexcept override {
506 _func(std::move(this->_state));
507 delete this;
508 }
509 Func _func;
510 };
511
512 namespace internal {
513
514 template <typename... T>
515 future<T...> make_exception_future(future_state_base&& state) noexcept;
516
517 template <typename... T, typename U>
518 void set_callback(future<T...>& fut, U* callback) noexcept;
519
520 class future_base;
521
522 class promise_base {
523 protected:
524 enum class urgent { no, yes };
525 future_base* _future = nullptr;
526
527 // This points to the future_state that is currently being
528 // used. See comment above the future_state struct definition for
529 // details.
530 future_state_base* _state;
531
532 task* _task = nullptr;
533
534 promise_base(const promise_base&) = delete;
535 promise_base(future_state_base* state) noexcept : _state(state) {}
536 promise_base(future_base* future, future_state_base* state) noexcept;
537 promise_base(promise_base&& x) noexcept;
538
539 // We never need to destruct this polymorphicly, so we can make it
540 // protected instead of virtual
541 ~promise_base() noexcept;
542
543 void operator=(const promise_base&) = delete;
544 promise_base& operator=(promise_base&& x) = delete;
545
546 template<urgent Urgent>
547 void make_ready() noexcept;
548
549 template<typename T>
550 void set_exception_impl(T&& val) noexcept {
551 if (_state) {
552 _state->set_exception(std::move(val));
553 make_ready<urgent::no>();
554 } else {
555 // We get here if promise::get_future is called and the
556 // returned future is destroyed without creating a
557 // continuation.
558 // In older versions of seastar we would store a local
559 // copy of ex and warn in the promise destructor.
560 // Since there isn't any way for the user to clear
561 // the exception, we issue the warning from here.
562 report_failed_future(val);
563 }
564 }
565
566 void set_exception(future_state_base&& state) noexcept {
567 set_exception_impl(std::move(state));
568 }
569
570 void set_exception(std::exception_ptr&& ex) noexcept {
571 set_exception_impl(std::move(ex));
572 }
573
574 void set_exception(const std::exception_ptr& ex) noexcept {
575 set_exception(std::exception_ptr(ex));
576 }
577
578 template<typename Exception>
579 std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
580 set_exception(make_exception_ptr(std::forward<Exception>(e)));
581 }
582
583 friend class future_base;
584 template <typename... U> friend class seastar::future;
585 };
586
587 /// \brief A promise with type but no local data.
588 ///
589 /// This is a promise without any local data. We use this for when the
590 /// future is created first, so we know the promise always has an
591 /// external place to point to. We cannot just use promise_base
592 /// because we need to know the type that is being stored.
593 template <typename... T>
594 class promise_base_with_type : protected internal::promise_base {
595 protected:
596 future_state<T...>* get_state() {
597 return static_cast<future_state<T...>*>(_state);
598 }
599 static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
600 public:
601 promise_base_with_type(future_state_base* state) noexcept : promise_base(state) { }
602 promise_base_with_type(future<T...>* future) noexcept : promise_base(future, &future->_state) { }
603 promise_base_with_type(promise_base_with_type&& x) noexcept : promise_base(std::move(x)) { }
604 promise_base_with_type(const promise_base_with_type&) = delete;
605 promise_base_with_type& operator=(promise_base_with_type&& x) noexcept {
606 this->~promise_base_with_type();
607 new (this) promise_base_with_type(std::move(x));
608 return *this;
609 }
610 void operator=(const promise_base_with_type&) = delete;
611
612 void set_urgent_state(future_state<T...>&& state) noexcept {
613 if (_state) {
614 *get_state() = std::move(state);
615 make_ready<urgent::yes>();
616 }
617 }
618
619 template <typename... A>
620 void set_value(A&&... a) {
621 if (auto *s = get_state()) {
622 s->set(std::forward<A>(a)...);
623 make_ready<urgent::no>();
624 }
625 }
626
627 #if SEASTAR_COROUTINES_TS
628 void set_coroutine(future_state<T...>& state, task& coroutine) noexcept {
629 _state = &state;
630 _task = &coroutine;
631 }
632 #endif
633 private:
634 template <typename Func>
635 void schedule(Func&& func) noexcept {
636 auto tws = new continuation<Func, T...>(std::move(func));
637 _state = &tws->_state;
638 _task = tws;
639 }
640 void schedule(continuation_base<T...>* callback) noexcept {
641 _state = &callback->_state;
642 _task = callback;
643 }
644
645 template <typename... U>
646 friend class seastar::future;
647
648 friend struct seastar::future_state<T...>;
649 };
650 }
651 /// \endcond
652
653 /// \brief promise - allows a future value to be made available at a later time.
654 ///
655 /// \tparam T A list of types to be carried as the result of the associated future.
656 /// A list with two or more types is deprecated; use
657 /// \c promise<std::tuple<T...>> instead.
658 template <typename... T>
659 class promise : private internal::promise_base_with_type<T...> {
660 future_state<T...> _local_state;
661
662 public:
663 /// \brief Constructs an empty \c promise.
664 ///
665 /// Creates promise with no associated future yet (see get_future()).
666 promise() noexcept : internal::promise_base_with_type<T...>(&_local_state) {}
667
668 /// \brief Moves a \c promise object.
669 promise(promise&& x) noexcept;
670 promise(const promise&) = delete;
671 promise& operator=(promise&& x) noexcept {
672 this->~promise();
673 new (this) promise(std::move(x));
674 return *this;
675 }
676 void operator=(const promise&) = delete;
677
678 /// \brief Gets the promise's associated future.
679 ///
680 /// The future and promise will be remember each other, even if either or
681 /// both are moved. When \c set_value() or \c set_exception() are called
682 /// on the promise, the future will be become ready, and if a continuation
683 /// was attached to the future, it will run.
684 future<T...> get_future() noexcept;
685
686 /// \brief Sets the promises value
687 ///
688 /// Forwards the arguments and makes them available to the associated
689 /// future. May be called either before or after \c get_future().
690 ///
691 /// The arguments can have either the types the promise is
692 /// templated with, or a corresponding std::tuple. That is, given
693 /// a promise<int, double>, both calls are valid:
694 ///
695 /// pr.set_value(42, 43.0);
696 /// pr.set_value(std::tuple<int, double>(42, 43.0))
697 template <typename... A>
698 void set_value(A&&... a) {
699 internal::promise_base_with_type<T...>::set_value(std::forward<A>(a)...);
700 }
701
702 /// \brief Marks the promise as failed
703 ///
704 /// Forwards the exception argument to the future and makes it
705 /// available. May be called either before or after \c get_future().
706 void set_exception(std::exception_ptr&& ex) noexcept {
707 internal::promise_base::set_exception(std::move(ex));
708 }
709
710 void set_exception(const std::exception_ptr& ex) noexcept {
711 internal::promise_base::set_exception(ex);
712 }
713
714 /// \brief Marks the promise as failed
715 ///
716 /// Forwards the exception argument to the future and makes it
717 /// available. May be called either before or after \c get_future().
718 template<typename Exception>
719 std::enable_if_t<!std::is_same<std::remove_reference_t<Exception>, std::exception_ptr>::value, void> set_exception(Exception&& e) noexcept {
720 internal::promise_base::set_exception(std::forward<Exception>(e));
721 }
722
723 using internal::promise_base_with_type<T...>::set_urgent_state;
724
725 template <typename... U>
726 friend class future;
727 };
728
729 /// \brief Specialization of \c promise<void>
730 ///
731 /// This is an alias for \c promise<>, for generic programming purposes.
732 /// For example, You may have a \c promise<T> where \c T can legally be
733 /// \c void.
734 template<>
735 class promise<void> : public promise<> {};
736
737 /// @}
738
739 /// \addtogroup future-util
740 /// @{
741
742
743 /// \brief Check whether a type is a future
744 ///
745 /// This is a type trait evaluating to \c true if the given type is a
746 /// future.
747 ///
748 template <typename... T> struct is_future : std::false_type {};
749
750 /// \cond internal
751 /// \addtogroup future-util
752 template <typename... T> struct is_future<future<T...>> : std::true_type {};
753
754 /// \endcond
755
756
757 /// \brief Converts a type to a future type, if it isn't already.
758 ///
759 /// \return Result in member type 'type'.
760 template <typename T>
761 struct futurize;
762
763 template <typename T>
764 struct futurize {
765 /// If \c T is a future, \c T; otherwise \c future<T>
766 using type = future<T>;
767 /// The promise type associated with \c type.
768 using promise_type = promise<T>;
769 /// The value tuple type associated with \c type
770 using value_type = std::tuple<T>;
771
772 /// Apply a function to an argument list (expressed as a tuple)
773 /// and return the result, as a future (if it wasn't already).
774 template<typename Func, typename... FuncArgs>
775 static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
776
777 /// Apply a function to an argument list
778 /// and return the result, as a future (if it wasn't already).
779 template<typename Func, typename... FuncArgs>
780 static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
781
782 /// Convert a value or a future to a future
783 static inline type convert(T&& value) { return make_ready_future<T>(std::move(value)); }
784 static inline type convert(type&& value) { return std::move(value); }
785
786 /// Convert the tuple representation into a future
787 static type from_tuple(value_type&& value);
788 /// Convert the tuple representation into a future
789 static type from_tuple(const value_type& value);
790
791 /// Makes an exceptional future of type \ref type.
792 template <typename Arg>
793 static type make_exception_future(Arg&& arg);
794 };
795
796 /// \cond internal
797 template <>
798 struct futurize<void> {
799 using type = future<>;
800 using promise_type = promise<>;
801 using value_type = std::tuple<>;
802
803 template<typename Func, typename... FuncArgs>
804 static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
805
806 template<typename Func, typename... FuncArgs>
807 static inline type apply(Func&& func, FuncArgs&&... args) noexcept;
808
809 static inline type from_tuple(value_type&& value);
810 static inline type from_tuple(const value_type& value);
811
812 template <typename Arg>
813 static type make_exception_future(Arg&& arg);
814 };
815
816 template <typename... Args>
817 struct futurize<future<Args...>> {
818 using type = future<Args...>;
819 using promise_type = promise<Args...>;
820 using value_type = std::tuple<Args...>;
821
822 template<typename Func, typename... FuncArgs>
823 static inline type apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept;
824
825 template<typename Func, typename... FuncArgs>
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 static inline type convert(Args&&... values) { return make_ready_future<Args...>(std::move(values)...); }
832 static inline type convert(type&& value) { return std::move(value); }
833
834 template <typename Arg>
835 static type make_exception_future(Arg&& arg);
836 };
837 /// \endcond
838
839 // Converts a type to a future type, if it isn't already.
840 template <typename T>
841 using futurize_t = typename futurize<T>::type;
842
843 /// @}
844
845 GCC6_CONCEPT(
846
847 template <typename T>
848 concept bool Future = is_future<T>::value;
849
850 template <typename Func, typename... T>
851 concept bool CanApply = requires (Func f, T... args) {
852 f(std::forward<T>(args)...);
853 };
854
855 template <typename Func, typename Return, typename... T>
856 concept bool ApplyReturns = requires (Func f, T... args) {
857 { f(std::forward<T>(args)...) } -> Return;
858 };
859
860 template <typename Func, typename... T>
861 concept bool ApplyReturnsAnyFuture = requires (Func f, T... args) {
862 requires is_future<decltype(f(std::forward<T>(args)...))>::value;
863 };
864
865 )
866
867 /// \addtogroup future-module
868 /// @{
869 namespace internal {
870 class future_base {
871 protected:
872 promise_base* _promise;
873 future_base() noexcept : _promise(nullptr) {}
874 future_base(promise_base* promise, future_state_base* state) noexcept : _promise(promise) {
875 _promise->_future = this;
876 _promise->_state = state;
877 }
878
879 future_base(future_base&& x, future_state_base* state) noexcept : _promise(x._promise) {
880 if (auto* p = _promise) {
881 x.detach_promise();
882 p->_future = this;
883 p->_state = state;
884 }
885 }
886 ~future_base() noexcept {
887 if (_promise) {
888 detach_promise();
889 }
890 }
891
892 promise_base* detach_promise() noexcept {
893 _promise->_state = nullptr;
894 _promise->_future = nullptr;
895 return std::exchange(_promise, nullptr);
896 }
897
898 friend class promise_base;
899 };
900
901 template <bool IsVariadic>
902 struct warn_variadic_future {
903 // Non-varidic case, do nothing
904 void check_deprecation() {}
905 };
906
907
908 // Note: placing the deprecated attribute on the class specialization has no effect.
909 template <>
910 struct warn_variadic_future<true> {
911 // Variadic case, has deprecation attribute
912 [[deprecated("Variadic future<> with more than one template parmeter is deprecated, replace with future<std::tuple<...>>")]]
913 void check_deprecation() {}
914 };
915
916 }
917
918 /// \brief A representation of a possibly not-yet-computed value.
919 ///
920 /// A \c future represents a value that has not yet been computed
921 /// (an asynchronous computation). It can be in one of several
922 /// states:
923 /// - unavailable: the computation has not been completed yet
924 /// - value: the computation has been completed successfully and a
925 /// value is available.
926 /// - failed: the computation completed with an exception.
927 ///
928 /// methods in \c future allow querying the state and, most importantly,
929 /// scheduling a \c continuation to be executed when the future becomes
930 /// available. Only one such continuation may be scheduled.
931 ///
932 /// A \ref future should not be discarded before it is waited upon and
933 /// its result is extracted. Discarding a \ref future means that the
934 /// computed value becomes inaccessible, but more importantly, any
935 /// exceptions raised from the computation will disappear unchecked as
936 /// well. Another very important consequence is potentially unbounded
937 /// resource consumption due to the launcher of the deserted
938 /// continuation not being able track the amount of in-progress
939 /// continuations, nor their individual resource consumption.
940 /// To prevent accidental discarding of futures, \ref future is
941 /// declared `[[nodiscard]]` if the compiler supports it. Also, when a
942 /// discarded \ref future resolves with an error a warning is logged
943 /// (at runtime).
944 /// That said there can be legitimate cases where a \ref future is
945 /// discarded. The most prominent example is launching a new
946 /// [fiber](\ref fiber-module), or in other words, moving a continuation
947 /// chain to the background (off the current [fiber](\ref fiber-module)).
948 /// Even if a \ref future is discarded purposefully, it is still strongly
949 /// advisable to wait on it indirectly (via a \ref gate or
950 /// \ref semaphore), control their concurrency, their resource consumption
951 /// and handle any errors raised from them.
952 ///
953 /// \tparam T A list of types to be carried as the result of the future,
954 /// similar to \c std::tuple<T...>. An empty list (\c future<>)
955 /// means that there is no result, and an available future only
956 /// contains a success/failure indication (and in the case of a
957 /// failure, an exception).
958 /// A list with two or more types is deprecated; use
959 /// \c future<std::tuple<T...>> instead.
960 template <typename... T>
961 class SEASTAR_NODISCARD future : private internal::future_base, internal::warn_variadic_future<(sizeof...(T) > 1)> {
962 future_state<T...> _state;
963 static constexpr bool copy_noexcept = future_state<T...>::copy_noexcept;
964 private:
965 // This constructor creates a future that is not ready but has no
966 // associated promise yet. The use case is to have a less flexible
967 // but more efficient future/promise pair where we know that
968 // promise::set_value cannot possibly be called without a matching
969 // future and so that promise doesn't need to store a
970 // future_state.
971 future(future_for_get_promise_marker m) { }
972
973 future(promise<T...>* pr) noexcept : future_base(pr, &_state), _state(std::move(pr->_local_state)) { }
974 template <typename... A>
975 future(ready_future_marker m, A&&... a) : _state(m, std::forward<A>(a)...) { }
976 future(exception_future_marker m, std::exception_ptr&& ex) noexcept : _state(m, std::move(ex)) { }
977 future(exception_future_marker m, future_state_base&& state) noexcept : _state(m, std::move(state)) { }
978 [[gnu::always_inline]]
979 explicit future(future_state<T...>&& state) noexcept
980 : _state(std::move(state)) {
981 this->check_deprecation();
982 }
983 internal::promise_base_with_type<T...> get_promise() noexcept {
984 assert(!_promise);
985 return internal::promise_base_with_type<T...>(this);
986 }
987 internal::promise_base_with_type<T...>* detach_promise() {
988 return static_cast<internal::promise_base_with_type<T...>*>(future_base::detach_promise());
989 }
990 template <typename Func>
991 void schedule(Func&& func) noexcept {
992 if (_state.available() || !_promise) {
993 if (__builtin_expect(!_state.available() && !_promise, false)) {
994 _state.set_to_broken_promise();
995 }
996 ::seastar::schedule(new continuation<Func, T...>(std::move(func), std::move(_state)));
997 } else {
998 assert(_promise);
999 detach_promise()->schedule(std::move(func));
1000 _state._u.st = future_state_base::state::invalid;
1001 }
1002 }
1003
1004 [[gnu::always_inline]]
1005 future_state<T...>&& get_available_state_ref() noexcept {
1006 if (_promise) {
1007 detach_promise();
1008 }
1009 return std::move(_state);
1010 }
1011
1012 [[gnu::noinline]]
1013 future<T...> rethrow_with_nested() {
1014 if (!failed()) {
1015 return internal::current_exception_as_future<T...>();
1016 } else {
1017 //
1018 // Encapsulate the current exception into the
1019 // std::nested_exception because the current libstdc++
1020 // implementation has a bug requiring the value of a
1021 // std::throw_with_nested() parameter to be of a polymorphic
1022 // type.
1023 //
1024 std::nested_exception f_ex;
1025 try {
1026 get();
1027 } catch (...) {
1028 std::throw_with_nested(f_ex);
1029 }
1030 __builtin_unreachable();
1031 }
1032 }
1033
1034 template<typename... U>
1035 friend class shared_future;
1036 public:
1037 /// \brief The data type carried by the future.
1038 using value_type = std::tuple<T...>;
1039 /// \brief The data type carried by the future.
1040 using promise_type = promise<T...>;
1041 /// \brief Moves the future into a new object.
1042 [[gnu::always_inline]]
1043 future(future&& x) noexcept : future_base(std::move(x), &_state), _state(std::move(x._state)) { }
1044 future(const future&) = delete;
1045 future& operator=(future&& x) noexcept {
1046 this->~future();
1047 new (this) future(std::move(x));
1048 return *this;
1049 }
1050 void operator=(const future&) = delete;
1051 /// \brief gets the value returned by the computation
1052 ///
1053 /// Requires that the future be available. If the value
1054 /// was computed successfully, it is returned (as an
1055 /// \c std::tuple). Otherwise, an exception is thrown.
1056 ///
1057 /// If get() is called in a \ref seastar::thread context,
1058 /// then it need not be available; instead, the thread will
1059 /// be paused until the future becomes available.
1060 [[gnu::always_inline]]
1061 std::tuple<T...>&& get() {
1062 if (!_state.available()) {
1063 do_wait();
1064 }
1065 return get_available_state_ref().take();
1066 }
1067
1068 [[gnu::always_inline]]
1069 std::exception_ptr get_exception() {
1070 return get_available_state_ref().get_exception();
1071 }
1072
1073 /// Gets the value returned by the computation.
1074 ///
1075 /// Similar to \ref get(), but instead of returning a
1076 /// tuple, returns the first value of the tuple. This is
1077 /// useful for the common case of a \c future<T> with exactly
1078 /// one type parameter.
1079 ///
1080 /// Equivalent to: \c std::get<0>(f.get()).
1081 typename future_state<T...>::get0_return_type get0() {
1082 return future_state<T...>::get0(get());
1083 }
1084
1085 /// Wait for the future to be available (in a seastar::thread)
1086 ///
1087 /// When called from a seastar::thread, this function blocks the
1088 /// thread until the future is availble. Other threads and
1089 /// continuations continue to execute; only the thread is blocked.
1090 void wait() noexcept {
1091 if (!_state.available()) {
1092 do_wait();
1093 }
1094 }
1095 private:
1096 class thread_wake_task final : public continuation_base<T...> {
1097 thread_context* _thread;
1098 future* _waiting_for;
1099 public:
1100 thread_wake_task(thread_context* thread, future* waiting_for)
1101 : _thread(thread), _waiting_for(waiting_for) {
1102 }
1103 virtual void run_and_dispose() noexcept override {
1104 _waiting_for->_state = std::move(this->_state);
1105 thread_impl::switch_in(_thread);
1106 // no need to delete, since this is always allocated on
1107 // _thread's stack.
1108 }
1109 };
1110 void do_wait() noexcept {
1111 if (__builtin_expect(!_promise, false)) {
1112 _state.set_to_broken_promise();
1113 return;
1114 }
1115 auto thread = thread_impl::get();
1116 assert(thread);
1117 thread_wake_task wake_task{thread, this};
1118 detach_promise()->schedule(static_cast<continuation_base<T...>*>(&wake_task));
1119 thread_impl::switch_out(thread);
1120 }
1121
1122 public:
1123 /// \brief Checks whether the future is available.
1124 ///
1125 /// \return \c true if the future has a value, or has failed.
1126 [[gnu::always_inline]]
1127 bool available() const noexcept {
1128 return _state.available();
1129 }
1130
1131 /// \brief Checks whether the future has failed.
1132 ///
1133 /// \return \c true if the future is availble and has failed.
1134 [[gnu::always_inline]]
1135 bool failed() const noexcept {
1136 return _state.failed();
1137 }
1138
1139 /// \brief Schedule a block of code to run when the future is ready.
1140 ///
1141 /// Schedules a function (often a lambda) to run when the future becomes
1142 /// available. The function is called with the result of this future's
1143 /// computation as parameters. The return value of the function becomes
1144 /// the return value of then(), itself as a future; this allows then()
1145 /// calls to be chained.
1146 ///
1147 /// If the future failed, the function is not called, and the exception
1148 /// is propagated into the return value of then().
1149 ///
1150 /// \param func - function to be called when the future becomes available,
1151 /// unless it has failed.
1152 /// \return a \c future representing the return value of \c func, applied
1153 /// to the eventual value of this future.
1154 template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1155 GCC6_CONCEPT( requires ::seastar::CanApply<Func, T...> )
1156 Result
1157 then(Func&& func) noexcept {
1158 #ifndef SEASTAR_TYPE_ERASE_MORE
1159 return then_impl(std::move(func));
1160 #else
1161 using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1162 return then_impl(noncopyable_function<Result (T&&...)>([func = std::forward<Func>(func)] (T&&... args) mutable {
1163 return futurator::apply(func, std::forward_as_tuple(std::move(args)...));
1164 }));
1165 #endif
1166 }
1167
1168 private:
1169
1170 template <typename Func, typename Result = futurize_t<std::result_of_t<Func(T&&...)>>>
1171 Result
1172 then_impl(Func&& func) noexcept {
1173 using futurator = futurize<std::result_of_t<Func(T&&...)>>;
1174 if (available() && !need_preempt()) {
1175 if (failed()) {
1176 return futurator::make_exception_future(static_cast<future_state_base&&>(get_available_state_ref()));
1177 } else {
1178 return futurator::apply(std::forward<Func>(func), get_available_state_ref().take_value());
1179 }
1180 }
1181 typename futurator::type fut(future_for_get_promise_marker{});
1182 // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1183 // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1184 // that happens.
1185 [&] () noexcept {
1186 memory::disable_failure_guard dfg;
1187 schedule([pr = fut.get_promise(), func = std::forward<Func>(func)] (future_state<T...>&& state) mutable {
1188 if (state.failed()) {
1189 pr.set_exception(static_cast<future_state_base&&>(std::move(state)));
1190 } else {
1191 futurator::apply(std::forward<Func>(func), std::move(state).get_value()).forward_to(std::move(pr));
1192 }
1193 });
1194 } ();
1195 return fut;
1196 }
1197
1198 public:
1199 /// \brief Schedule a block of code to run when the future is ready, allowing
1200 /// for exception handling.
1201 ///
1202 /// Schedules a function (often a lambda) to run when the future becomes
1203 /// available. The function is called with the this future as a parameter;
1204 /// it will be in an available state. The return value of the function becomes
1205 /// the return value of then_wrapped(), itself as a future; this allows
1206 /// then_wrapped() calls to be chained.
1207 ///
1208 /// Unlike then(), the function will be called for both value and exceptional
1209 /// futures.
1210 ///
1211 /// \param func - function to be called when the future becomes available,
1212 /// \return a \c future representing the return value of \c func, applied
1213 /// to the eventual value of this future.
1214 template <typename Func, typename FuncResult = std::result_of_t<Func(future)>>
1215 GCC6_CONCEPT( requires ::seastar::CanApply<Func, future> )
1216 futurize_t<FuncResult>
1217 then_wrapped(Func&& func) & noexcept {
1218 return then_wrapped_maybe_erase<false, FuncResult>(std::forward<Func>(func));
1219 }
1220
1221 template <typename Func, typename FuncResult = std::result_of_t<Func(future&&)>>
1222 GCC6_CONCEPT( requires ::seastar::CanApply<Func, future&&> )
1223 futurize_t<FuncResult>
1224 then_wrapped(Func&& func) && noexcept {
1225 return then_wrapped_maybe_erase<true, FuncResult>(std::forward<Func>(func));
1226 }
1227
1228 private:
1229
1230 template <bool AsSelf, typename FuncResult, typename Func>
1231 futurize_t<FuncResult>
1232 then_wrapped_maybe_erase(Func&& func) noexcept {
1233 #ifndef SEASTAR_TYPE_ERASE_MORE
1234 return then_wrapped_common<AsSelf, FuncResult>(std::forward<Func>(func));
1235 #else
1236 using futurator = futurize<FuncResult>;
1237 return then_wrapped_common<AsSelf, FuncResult>(noncopyable_function<typename futurator::type (future&&)>([func = std::forward<Func>(func)] (future&& f) mutable {
1238 return futurator::apply(std::forward<Func>(func), std::move(f));
1239 }));
1240 #endif
1241 }
1242
1243 template <bool AsSelf, typename FuncResult, typename Func>
1244 futurize_t<FuncResult>
1245 then_wrapped_common(Func&& func) noexcept {
1246 using futurator = futurize<FuncResult>;
1247 if (available() && !need_preempt()) {
1248 // TODO: after dropping C++14 support use `if constexpr ()` instead.
1249 if (AsSelf) {
1250 if (_promise) {
1251 detach_promise();
1252 }
1253 return futurator::apply(std::forward<Func>(func), std::move(*this));
1254 } else {
1255 return futurator::apply(std::forward<Func>(func), future(get_available_state_ref()));
1256 }
1257 }
1258 typename futurator::type fut(future_for_get_promise_marker{});
1259 // If there is a std::bad_alloc in schedule() there is nothing that can be done about it, we cannot break future
1260 // chain by returning ready future while 'this' future is not ready. The noexcept will call std::terminate if
1261 // that happens.
1262 [&] () noexcept {
1263 memory::disable_failure_guard dfg;
1264 schedule([pr = fut.get_promise(), func = std::forward<Func>(func)] (future_state<T...>&& state) mutable {
1265 futurator::apply(std::forward<Func>(func), future(std::move(state))).forward_to(std::move(pr));
1266 });
1267 } ();
1268 return fut;
1269 }
1270
1271 void forward_to(internal::promise_base_with_type<T...>&& pr) noexcept {
1272 if (_state.available()) {
1273 pr.set_urgent_state(std::move(_state));
1274 } else {
1275 *detach_promise() = std::move(pr);
1276 }
1277 }
1278
1279 public:
1280 /// \brief Satisfy some \ref promise object with this future as a result.
1281 ///
1282 /// Arranges so that when this future is resolve, it will be used to
1283 /// satisfy an unrelated promise. This is similar to scheduling a
1284 /// continuation that moves the result of this future into the promise
1285 /// (using promise::set_value() or promise::set_exception(), except
1286 /// that it is more efficient.
1287 ///
1288 /// \param pr a promise that will be fulfilled with the results of this
1289 /// future.
1290 void forward_to(promise<T...>&& pr) noexcept {
1291 if (_state.available()) {
1292 pr.set_urgent_state(std::move(_state));
1293 } else if (&pr._local_state != pr._state) {
1294 // The only case when _state points to _local_state is
1295 // when get_future was never called. Given that pr will
1296 // soon be destroyed, we know get_future will never be
1297 // called and we can just ignore this request.
1298 *detach_promise() = std::move(pr);
1299 }
1300 }
1301
1302
1303
1304 /**
1305 * Finally continuation for statements that require waiting for the result.
1306 * I.e. you need to "finally" call a function that returns a possibly
1307 * unavailable future. The returned future will be "waited for", any
1308 * exception generated will be propagated, but the return value is ignored.
1309 * I.e. the original return value (the future upon which you are making this
1310 * call) will be preserved.
1311 *
1312 * If the original return value or the callback return value is an
1313 * exceptional future it will be propagated.
1314 *
1315 * If both of them are exceptional - the std::nested_exception exception
1316 * with the callback exception on top and the original future exception
1317 * nested will be propagated.
1318 */
1319 template <typename Func>
1320 GCC6_CONCEPT( requires ::seastar::CanApply<Func> )
1321 future<T...> finally(Func&& func) noexcept {
1322 return then_wrapped(finally_body<Func, is_future<std::result_of_t<Func()>>::value>(std::forward<Func>(func)));
1323 }
1324
1325
1326 template <typename Func, bool FuncReturnsFuture>
1327 struct finally_body;
1328
1329 template <typename Func>
1330 struct finally_body<Func, true> {
1331 Func _func;
1332
1333 finally_body(Func&& func) : _func(std::forward<Func>(func))
1334 { }
1335
1336 future<T...> operator()(future<T...>&& result) {
1337 using futurator = futurize<std::result_of_t<Func()>>;
1338 return futurator::apply(_func).then_wrapped([result = std::move(result)](auto f_res) mutable {
1339 if (!f_res.failed()) {
1340 return std::move(result);
1341 } else {
1342 try {
1343 f_res.get();
1344 } catch (...) {
1345 return result.rethrow_with_nested();
1346 }
1347 __builtin_unreachable();
1348 }
1349 });
1350 }
1351 };
1352
1353 template <typename Func>
1354 struct finally_body<Func, false> {
1355 Func _func;
1356
1357 finally_body(Func&& func) : _func(std::forward<Func>(func))
1358 { }
1359
1360 future<T...> operator()(future<T...>&& result) {
1361 try {
1362 _func();
1363 return std::move(result);
1364 } catch (...) {
1365 return result.rethrow_with_nested();
1366 }
1367 };
1368 };
1369
1370 /// \brief Terminate the program if this future fails.
1371 ///
1372 /// Terminates the entire program is this future resolves
1373 /// to an exception. Use with caution.
1374 future<> or_terminate() noexcept {
1375 return then_wrapped([] (auto&& f) {
1376 try {
1377 f.get();
1378 } catch (...) {
1379 engine_exit(std::current_exception());
1380 }
1381 });
1382 }
1383
1384 /// \brief Discards the value carried by this future.
1385 ///
1386 /// Converts the future into a no-value \c future<>, by
1387 /// ignoring any result. Exceptions are propagated unchanged.
1388 future<> discard_result() noexcept {
1389 return then([] (T&&...) {});
1390 }
1391
1392 /// \brief Handle the exception carried by this future.
1393 ///
1394 /// When the future resolves, if it resolves with an exception,
1395 /// handle_exception(func) replaces the exception with the value
1396 /// returned by func. The exception is passed (as a std::exception_ptr)
1397 /// as a parameter to func; func may return the replacement value
1398 /// immediately (T or std::tuple<T...>) or in the future (future<T...>)
1399 /// and is even allowed to return (or throw) its own exception.
1400 ///
1401 /// The idiom fut.discard_result().handle_exception(...) can be used
1402 /// to handle an exception (if there is one) without caring about the
1403 /// successful value; Because handle_exception() is used here on a
1404 /// future<>, the handler function does not need to return anything.
1405 template <typename Func>
1406 /* Broken?
1407 GCC6_CONCEPT( requires ::seastar::ApplyReturns<Func, future<T...>, std::exception_ptr>
1408 || (sizeof...(T) == 0 && ::seastar::ApplyReturns<Func, void, std::exception_ptr>)
1409 || (sizeof...(T) == 1 && ::seastar::ApplyReturns<Func, T..., std::exception_ptr>)
1410 ) */
1411 future<T...> handle_exception(Func&& func) noexcept {
1412 using func_ret = std::result_of_t<Func(std::exception_ptr)>;
1413 return then_wrapped([func = std::forward<Func>(func)]
1414 (auto&& fut) mutable -> future<T...> {
1415 if (!fut.failed()) {
1416 return make_ready_future<T...>(fut.get());
1417 } else {
1418 return futurize<func_ret>::apply(func, fut.get_exception());
1419 }
1420 });
1421 }
1422
1423 /// \brief Handle the exception of a certain type carried by this future.
1424 ///
1425 /// When the future resolves, if it resolves with an exception of a type that
1426 /// provided callback receives as a parameter, handle_exception(func) replaces
1427 /// the exception with the value returned by func. The exception is passed (by
1428 /// reference) as a parameter to func; func may return the replacement value
1429 /// immediately (T or std::tuple<T...>) or in the future (future<T...>)
1430 /// and is even allowed to return (or throw) its own exception.
1431 /// If exception, that future holds, does not match func parameter type
1432 /// it is propagated as is.
1433 template <typename Func>
1434 future<T...> handle_exception_type(Func&& func) noexcept {
1435 using trait = function_traits<Func>;
1436 static_assert(trait::arity == 1, "func can take only one parameter");
1437 using ex_type = typename trait::template arg<0>::type;
1438 using func_ret = typename trait::return_type;
1439 return then_wrapped([func = std::forward<Func>(func)]
1440 (auto&& fut) mutable -> future<T...> {
1441 try {
1442 return make_ready_future<T...>(fut.get());
1443 } catch(ex_type& ex) {
1444 return futurize<func_ret>::apply(func, ex);
1445 }
1446 });
1447 }
1448
1449 /// \brief Ignore any result hold by this future
1450 ///
1451 /// Ignore any result (value or exception) hold by this future.
1452 /// Use with caution since usually ignoring exception is not what
1453 /// you want
1454 void ignore_ready_future() noexcept {
1455 _state.ignore();
1456 }
1457
1458 #if SEASTAR_COROUTINES_TS
1459 void set_coroutine(task& coroutine) noexcept {
1460 assert(!_state.available());
1461 assert(_promise);
1462 detach_promise()->set_coroutine(_state, coroutine);
1463 }
1464 #endif
1465 private:
1466 void set_callback(continuation_base<T...>* callback) noexcept {
1467 if (_state.available()) {
1468 callback->set_state(get_available_state_ref());
1469 ::seastar::schedule(callback);
1470 } else {
1471 assert(_promise);
1472 detach_promise()->schedule(callback);
1473 }
1474
1475 }
1476
1477 /// \cond internal
1478 template <typename... U>
1479 friend class future;
1480 template <typename... U>
1481 friend class promise;
1482 template <typename... U>
1483 friend class internal::promise_base_with_type;
1484 template <typename... U, typename... A>
1485 friend future<U...> make_ready_future(A&&... value);
1486 template <typename... U>
1487 friend future<U...> make_exception_future(std::exception_ptr&& ex) noexcept;
1488 template <typename... U, typename Exception>
1489 friend future<U...> make_exception_future(Exception&& ex) noexcept;
1490 template <typename... U>
1491 friend future<U...> internal::make_exception_future(future_state_base&& state) noexcept;
1492 template <typename... U, typename V>
1493 friend void internal::set_callback(future<U...>&, V*) noexcept;
1494 /// \endcond
1495 };
1496
1497 inline internal::promise_base::promise_base(future_base* future, future_state_base* state) noexcept
1498 : _future(future), _state(state) {
1499 _future->_promise = this;
1500 }
1501
1502 template <typename... T>
1503 inline
1504 future<T...>
1505 promise<T...>::get_future() noexcept {
1506 assert(!this->_future && this->_state && !this->_task);
1507 return future<T...>(this);
1508 }
1509
1510 template <typename... T>
1511 inline
1512 promise<T...>::promise(promise&& x) noexcept : internal::promise_base_with_type<T...>(std::move(x)) {
1513 if (this->_state == &x._local_state) {
1514 this->_state = &_local_state;
1515 _local_state = std::move(x._local_state);
1516 }
1517 }
1518
1519 template <typename... T, typename... A>
1520 inline
1521 future<T...> make_ready_future(A&&... value) {
1522 return future<T...>(ready_future_marker(), std::forward<A>(value)...);
1523 }
1524
1525 template <typename... T>
1526 inline
1527 future<T...> make_exception_future(std::exception_ptr&& ex) noexcept {
1528 return future<T...>(exception_future_marker(), std::move(ex));
1529 }
1530
1531 template <typename... T>
1532 inline
1533 future<T...> internal::make_exception_future(future_state_base&& state) noexcept {
1534 return future<T...>(exception_future_marker(), std::move(state));
1535 }
1536
1537 template <typename... T>
1538 future<T...> internal::current_exception_as_future() noexcept {
1539 return internal::make_exception_future<T...>(future_state_base::current_exception());
1540 }
1541
1542 void log_exception_trace() noexcept;
1543
1544 /// \brief Creates a \ref future in an available, failed state.
1545 ///
1546 /// Creates a \ref future object that is already resolved in a failed
1547 /// state. This no I/O needs to be performed to perform a computation
1548 /// (for example, because the connection is closed and we cannot read
1549 /// from it).
1550 template <typename... T, typename Exception>
1551 inline
1552 future<T...> make_exception_future(Exception&& ex) noexcept {
1553 log_exception_trace();
1554 return make_exception_future<T...>(std::make_exception_ptr(std::forward<Exception>(ex)));
1555 }
1556
1557 /// @}
1558
1559 /// \cond internal
1560
1561 template<typename T>
1562 template<typename Func, typename... FuncArgs>
1563 typename futurize<T>::type futurize<T>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1564 try {
1565 return convert(::seastar::apply(std::forward<Func>(func), std::move(args)));
1566 } catch (...) {
1567 return internal::current_exception_as_future<T>();
1568 }
1569 }
1570
1571 template<typename T>
1572 template<typename Func, typename... FuncArgs>
1573 typename futurize<T>::type futurize<T>::apply(Func&& func, FuncArgs&&... args) noexcept {
1574 try {
1575 return convert(func(std::forward<FuncArgs>(args)...));
1576 } catch (...) {
1577 return internal::current_exception_as_future<T>();
1578 }
1579 }
1580
1581 template <typename Ret> // Ret = void | future<>
1582 struct do_void_futurize_helper;
1583
1584 template <>
1585 struct do_void_futurize_helper<void> {
1586 template <typename Func, typename... FuncArgs>
1587 static future<> apply(Func&& func, FuncArgs&&... args) noexcept {
1588 try {
1589 func(std::forward<FuncArgs>(args)...);
1590 return make_ready_future<>();
1591 } catch (...) {
1592 return internal::current_exception_as_future<>();
1593 }
1594 }
1595
1596 template<typename Func, typename... FuncArgs>
1597 static future<> apply_tuple(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1598 try {
1599 ::seastar::apply(std::forward<Func>(func), std::move(args));
1600 return make_ready_future<>();
1601 } catch (...) {
1602 return internal::current_exception_as_future<>();
1603 }
1604 }
1605 };
1606
1607 template <>
1608 struct do_void_futurize_helper<future<>> {
1609 template <typename Func, typename... FuncArgs>
1610 static future<> apply(Func&& func, FuncArgs&&... args) noexcept {
1611 try {
1612 return func(std::forward<FuncArgs>(args)...);
1613 } catch (...) {
1614 return internal::current_exception_as_future<>();
1615 }
1616 }
1617
1618 template<typename Func, typename... FuncArgs>
1619 static future<> apply_tuple(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1620 try {
1621 return ::seastar::apply(std::forward<Func>(func), std::move(args));
1622 } catch (...) {
1623 return internal::current_exception_as_future<>();
1624 }
1625 }
1626 };
1627
1628 template <typename Func, typename... FuncArgs>
1629 using void_futurize_helper = do_void_futurize_helper<std::result_of_t<Func(FuncArgs&&...)>>;
1630
1631 template<typename Func, typename... FuncArgs>
1632 typename futurize<void>::type futurize<void>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1633 return void_futurize_helper<Func, FuncArgs...>::apply_tuple(std::forward<Func>(func), std::move(args));
1634 }
1635
1636 template<typename Func, typename... FuncArgs>
1637 typename futurize<void>::type futurize<void>::apply(Func&& func, FuncArgs&&... args) noexcept {
1638 return void_futurize_helper<Func, FuncArgs...>::apply(std::forward<Func>(func), std::forward<FuncArgs>(args)...);
1639 }
1640
1641 template<typename... Args>
1642 template<typename Func, typename... FuncArgs>
1643 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, std::tuple<FuncArgs...>&& args) noexcept {
1644 try {
1645 return ::seastar::apply(std::forward<Func>(func), std::move(args));
1646 } catch (...) {
1647 return internal::current_exception_as_future<Args...>();
1648 }
1649 }
1650
1651 template<typename... Args>
1652 template<typename Func, typename... FuncArgs>
1653 typename futurize<future<Args...>>::type futurize<future<Args...>>::apply(Func&& func, FuncArgs&&... args) noexcept {
1654 try {
1655 return func(std::forward<FuncArgs>(args)...);
1656 } catch (...) {
1657 return internal::current_exception_as_future<Args...>();
1658 }
1659 }
1660
1661 template <typename T>
1662 template <typename Arg>
1663 inline
1664 future<T>
1665 futurize<T>::make_exception_future(Arg&& arg) {
1666 using ::seastar::make_exception_future;
1667 using ::seastar::internal::make_exception_future;
1668 return make_exception_future<T>(std::forward<Arg>(arg));
1669 }
1670
1671 template <typename... T>
1672 template <typename Arg>
1673 inline
1674 future<T...>
1675 futurize<future<T...>>::make_exception_future(Arg&& arg) {
1676 using ::seastar::make_exception_future;
1677 using ::seastar::internal::make_exception_future;
1678 return make_exception_future<T...>(std::forward<Arg>(arg));
1679 }
1680
1681 template <typename Arg>
1682 inline
1683 future<>
1684 futurize<void>::make_exception_future(Arg&& arg) {
1685 using ::seastar::make_exception_future;
1686 using ::seastar::internal::make_exception_future;
1687 return make_exception_future<>(std::forward<Arg>(arg));
1688 }
1689
1690 template <typename T>
1691 inline
1692 future<T>
1693 futurize<T>::from_tuple(std::tuple<T>&& value) {
1694 return make_ready_future<T>(std::move(value));
1695 }
1696
1697 template <typename T>
1698 inline
1699 future<T>
1700 futurize<T>::from_tuple(const std::tuple<T>& value) {
1701 return make_ready_future<T>(value);
1702 }
1703
1704 inline
1705 future<>
1706 futurize<void>::from_tuple(std::tuple<>&& value) {
1707 return make_ready_future<>();
1708 }
1709
1710 inline
1711 future<>
1712 futurize<void>::from_tuple(const std::tuple<>& value) {
1713 return make_ready_future<>();
1714 }
1715
1716 template <typename... Args>
1717 inline
1718 future<Args...>
1719 futurize<future<Args...>>::from_tuple(std::tuple<Args...>&& value) {
1720 return make_ready_future<Args...>(std::move(value));
1721 }
1722
1723 template <typename... Args>
1724 inline
1725 future<Args...>
1726 futurize<future<Args...>>::from_tuple(const std::tuple<Args...>& value) {
1727 return make_ready_future<Args...>(value);
1728 }
1729
1730 template<typename Func, typename... Args>
1731 auto futurize_apply(Func&& func, Args&&... args) {
1732 using futurator = futurize<std::result_of_t<Func(Args&&...)>>;
1733 return futurator::apply(std::forward<Func>(func), std::forward<Args>(args)...);
1734 }
1735
1736 namespace internal {
1737
1738 template <typename... T, typename U>
1739 inline
1740 void set_callback(future<T...>& fut, U* callback) noexcept {
1741 // It would be better to use continuation_base<T...> for U, but
1742 // then a derived class of continuation_base<T...> won't be matched
1743 return fut.set_callback(callback);
1744 }
1745
1746 }
1747
1748
1749 /// \endcond
1750
1751 }