-
Notifications
You must be signed in to change notification settings - Fork 19
Expand file tree
/
Copy pathAsyncCall.cpp
More file actions
74 lines (65 loc) · 2.34 KB
/
Copy pathAsyncCall.cpp
File metadata and controls
74 lines (65 loc) · 2.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
/*************************************************************************
> File Name: AsyncCall.cpp
> Author: Netcan
> Blog: https://netcan.github.io/
> Mail: netcan1996@gmail.com
> Created Time: 2021-12-19 15:31
************************************************************************/
#include <coroutine>
#include <concepts>
#include <future>
#include <iostream>
#include <iterator>
#include <vector>
#include <numeric>
struct AsCoroutine {};
inline constexpr AsCoroutine as_coroutine;
template<typename T, typename... Args>
struct std::coroutine_traits<std::future<T>, AsCoroutine, Args...> {
struct promise_type: std::promise<T> {
std::future<T> get_return_object() { return this->get_future(); }
auto initial_suspend() noexcept { return std::suspend_never{}; }
auto final_suspend() noexcept { return std::suspend_never{}; }
void unhandled_exception() {
this->set_exception(std::current_exception());
}
template<typename U>
void return_value(U&& value) {
this->set_value(std::forward<U>(value));
}
struct Awaiter {
bool await_ready() {
return fut_.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
void await_suspend(std::coroutine_handle<> handle) {
std::thread([=, this] {
fut_.wait();
handle.resume();
}).detach();
}
decltype(auto) await_resume() { return fut_.get(); }
std::future<T> fut_;
};
Awaiter await_transform(std::future<T> fut) {
return { std::move(fut) };
}
};
};
template<std::random_access_iterator RandIt>
std::future<int> parallel_sum(AsCoroutine, RandIt beg, RandIt end) {
auto len = end - beg;
if (len == 0) { co_return 0; }
RandIt mid = beg + len/2;
auto rest_task = std::async([](RandIt b, RandIt e) {
return std::accumulate(b, e, 0);
}, mid, end);
auto first_task = parallel_sum(as_coroutine, beg, mid);
auto first = co_await std::move(first_task);
auto rest = co_await std::move(rest_task);
co_return first + rest;
}
int main() {
std::vector v(100000000, 1);
std::cout << "The sum is " << parallel_sum(as_coroutine, v.begin(), v.end()).get() << '\n';
return 0;
}