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