mp-coro main
Coroutine support tools
async.h
Go to the documentation of this file.
1// The MIT License (MIT)
2//
3// Copyright (c) 2021 Mateusz Pusz
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23#pragma once
24
26#include <mp-coro/trace.h>
27#include <concepts>
28#include <coroutine>
29#include <thread>
30
31namespace mp_coro {
32
33template <std::invocable Func>
34class async {
35 public:
36 using return_type = std::invoke_result_t<Func>;
37 template <typename F>
38 requires std::same_as<std::remove_cvref_t<F>, Func> explicit async(F &&func)
39 : func_ {std::forward<F>(func)} {}
40
41 decltype(auto)
42 operator co_await() & = delete; // async should be co_awaited only once (on rvalue)
43 decltype(auto) operator co_await() && {
44 struct awaiter {
46 bool await_ready() const noexcept {
47 TRACE_FUNC();
48 return false;
49 }
50 void await_suspend(std::coroutine_handle<> handle) {
51 auto work = [&, handle]() {
52 TRACE_FUNC();
53 try {
54 if constexpr (std::is_void_v<return_type>)
55 awaitable.func_();
56 else
57 awaitable.result_.set_value(awaitable.func_());
58 } catch (...) {
59 awaitable.result_.set_exception(std::current_exception());
60 }
61 handle.resume();
62 };
63
64 TRACE_FUNC();
65 std::jthread(work).detach(); // TODO: Fix that (replace with a thread pool)
66 }
67 decltype(auto) await_resume() {
68 TRACE_FUNC();
69 return std::move(awaitable.result_).get();
70 }
71 };
72 return awaiter {*this};
73 }
74
75 private:
76 Func func_;
78};
79
80template <typename F>
82
83} // namespace mp_coro
std::invoke_result_t< Func > return_type
Definition: async.h:36
detail::storage< return_type > result_
Definition: async.h:77
async(F &&func)
Definition: async.h:38
Func func_
Definition: async.h:76
Storage class that can either contain a value, an exception, or be empty.
Definition: storage.h:90
Definition: async.h:31
bool await_ready() const noexcept
Returns true if the task's coroutine is already done (suspended at its final suspension point).
Definition: task.h:117
decltype(auto) await_resume() const
Return the value of the task's promise.
Definition: task.h:131
std::coroutine_handle await_suspend(std::coroutine_handle<> h) const noexcept
Set the current coroutine as this task's continuation, and then resume this task's coroutine.
Definition: task.h:124
#define TRACE_FUNC()
Definition: trace.h:27