]> git.proxmox.com Git - ceph.git/blob - ceph/src/seastar/include/seastar/core/coroutine.hh
import quincy beta 17.1.0
[ceph.git] / ceph / src / seastar / include / seastar / core / coroutine.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) 2019 ScyllaDB Ltd.
20 */
21
22 #pragma once
23
24 #include <seastar/core/future.hh>
25
26 #ifndef SEASTAR_COROUTINES_ENABLED
27 #error Coroutines support disabled.
28 #endif
29
30 #include <seastar/core/std-coroutine.hh>
31 #include <seastar/coroutine/exception.hh>
32
33 namespace seastar {
34
35 namespace internal {
36
37 template <typename T = void>
38 class coroutine_traits_base {
39 public:
40 class promise_type final : public seastar::task {
41 seastar::promise<T> _promise;
42 public:
43 promise_type() = default;
44 promise_type(promise_type&&) = delete;
45 promise_type(const promise_type&) = delete;
46
47 template<typename... U>
48 void return_value(U&&... value) {
49 _promise.set_value(std::forward<U>(value)...);
50 }
51
52 void return_value(coroutine::exception ce) noexcept {
53 _promise.set_exception(std::move(ce.eptr));
54 }
55
56 [[deprecated("Forwarding coroutine returns are deprecated as too dangerous. Use 'co_return co_await ...' until explicit syntax is available.")]]
57 void return_value(future<T>&& fut) noexcept {
58 fut.forward_to(std::move(_promise));
59 }
60
61 void unhandled_exception() noexcept {
62 _promise.set_exception(std::current_exception());
63 }
64
65 seastar::future<T> get_return_object() noexcept {
66 return _promise.get_future();
67 }
68
69 SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never initial_suspend() noexcept { return { }; }
70 SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never final_suspend() noexcept { return { }; }
71
72 virtual void run_and_dispose() noexcept override {
73 auto handle = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<promise_type>::from_promise(*this);
74 handle.resume();
75 }
76
77 task* waiting_task() noexcept override { return _promise.waiting_task(); }
78 };
79 };
80
81 template <>
82 class coroutine_traits_base<> {
83 public:
84 class promise_type final : public seastar::task {
85 seastar::promise<> _promise;
86 public:
87 promise_type() = default;
88 promise_type(promise_type&&) = delete;
89 promise_type(const promise_type&) = delete;
90
91 void return_void() noexcept {
92 _promise.set_value();
93 }
94
95 void unhandled_exception() noexcept {
96 _promise.set_exception(std::current_exception());
97 }
98
99 seastar::future<> get_return_object() noexcept {
100 return _promise.get_future();
101 }
102
103 SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never initial_suspend() noexcept { return { }; }
104 SEASTAR_INTERNAL_COROUTINE_NAMESPACE::suspend_never final_suspend() noexcept { return { }; }
105
106 virtual void run_and_dispose() noexcept override {
107 auto handle = SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<promise_type>::from_promise(*this);
108 handle.resume();
109 }
110
111 task* waiting_task() noexcept override { return _promise.waiting_task(); }
112 };
113 };
114
115 template<typename... T>
116 struct awaiter {
117 seastar::future<T...> _future;
118 public:
119 explicit awaiter(seastar::future<T...>&& f) noexcept : _future(std::move(f)) { }
120
121 awaiter(const awaiter&) = delete;
122 awaiter(awaiter&&) = delete;
123
124 bool await_ready() const noexcept {
125 return _future.available() && !need_preempt();
126 }
127
128 template<typename U>
129 void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
130 if (!_future.available()) {
131 _future.set_coroutine(hndl.promise());
132 } else {
133 schedule(&hndl.promise());
134 }
135 }
136
137 std::tuple<T...> await_resume() { return _future.get(); }
138 };
139
140 template<typename T>
141 struct awaiter<T> {
142 seastar::future<T> _future;
143 public:
144 explicit awaiter(seastar::future<T>&& f) noexcept : _future(std::move(f)) { }
145
146 awaiter(const awaiter&) = delete;
147 awaiter(awaiter&&) = delete;
148
149 bool await_ready() const noexcept {
150 return _future.available() && !need_preempt();
151 }
152
153 template<typename U>
154 void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
155 if (!_future.available()) {
156 _future.set_coroutine(hndl.promise());
157 } else {
158 schedule(&hndl.promise());
159 }
160 }
161
162 T await_resume() { return _future.get0(); }
163 };
164
165 template<>
166 struct awaiter<> {
167 seastar::future<> _future;
168 public:
169 explicit awaiter(seastar::future<>&& f) noexcept : _future(std::move(f)) { }
170
171 awaiter(const awaiter&) = delete;
172 awaiter(awaiter&&) = delete;
173
174 bool await_ready() const noexcept {
175 return _future.available() && !need_preempt();
176 }
177
178 template<typename U>
179 void await_suspend(SEASTAR_INTERNAL_COROUTINE_NAMESPACE::coroutine_handle<U> hndl) noexcept {
180 if (!_future.available()) {
181 _future.set_coroutine(hndl.promise());
182 } else {
183 schedule(&hndl.promise());
184 }
185 }
186
187 void await_resume() { _future.get(); }
188 };
189
190 } // seastar::internal
191
192 template<typename... T>
193 auto operator co_await(future<T...> f) noexcept {
194 return internal::awaiter<T...>(std::move(f));
195 }
196
197 } // seastar
198
199
200 namespace SEASTAR_INTERNAL_COROUTINE_NAMESPACE {
201
202 template<typename... T, typename... Args>
203 class coroutine_traits<seastar::future<T...>, Args...> : public seastar::internal::coroutine_traits_base<T...> {
204 };
205
206 } // SEASTAR_INTERNAL_COROUTINE_NAMESPACE
207