]> git.proxmox.com Git - ceph.git/blame - ceph/src/seastar/include/seastar/coroutine/maybe_yield.hh
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / seastar / include / seastar / coroutine / maybe_yield.hh
CommitLineData
20effc67
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) 2021-present ScyllaDB
20 */
21
22#pragma once
23
24#include <concepts>
25#include <type_traits>
26#include <seastar/core/coroutine.hh>
27
28namespace seastar::coroutine {
29
30namespace internal {
31
32struct maybe_yield_awaiter final : task {
1e59de90 33 using coroutine_handle_t = std::coroutine_handle<void>;
20effc67
TL
34
35 coroutine_handle_t when_ready;
36 task* main_coroutine_task;
37
38 bool await_ready() const {
39 return !need_preempt();
40 }
41
42 template <typename T>
1e59de90 43 void await_suspend(std::coroutine_handle<T> h) {
20effc67
TL
44 when_ready = h;
45 main_coroutine_task = &h.promise(); // for waiting_task()
46 schedule(this);
47 }
48
49 void await_resume() {
50 }
51
52 virtual void run_and_dispose() noexcept override {
53 when_ready.resume();
54 // No need to delete, this is allocated on the coroutine frame
55 }
56
57 virtual task* waiting_task() noexcept override {
58 return main_coroutine_task;
59 }
60};
61
62}
63
64/// Preempt if the current task quota expired.
65///
66/// `maybe_yield()` can be used to break a long computation in a
67/// coroutine and allow the reactor to preempt its execution. This
68/// allows other tasks to gain access to the CPU. If the task quota
69/// did not expire, the coroutine continues execution.
70///
71/// It should be used in long loops that do not contain other `co_await`
72/// calls.
73///
74/// Example
75///
76/// ```
77/// seastar::future<int> long_loop(int n) {
78/// float acc = 0;
79/// for (int i = 0; i < n; ++i) {
80/// acc += std::sin(float(i));
81/// co_await seastar::coroutine::maybe_yield();
82/// }
83/// co_return acc;
84/// }
85/// ```
86class [[nodiscard("must co_await an maybe_yield() object")]] maybe_yield {
87public:
88 auto operator co_await() { return internal::maybe_yield_awaiter(); }
89};
90
91}