forked from lewissbaker/cppcoro
-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathschedule_on.hpp
More file actions
69 lines (57 loc) · 1.99 KB
/
schedule_on.hpp
File metadata and controls
69 lines (57 loc) · 1.99 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
///////////////////////////////////////////////////////////////////////////////
// Copyright (c) Lewis Baker
// Licenced under MIT license. See LICENSE.txt for details.
///////////////////////////////////////////////////////////////////////////////
#ifndef CPPCORO_SCHEDULE_ON_HPP_INCLUDED
#define CPPCORO_SCHEDULE_ON_HPP_INCLUDED
#include <cppcoro/task.hpp>
#include <cppcoro/shared_task.hpp>
#include <cppcoro/async_generator.hpp>
#include <cppcoro/awaitable_traits.hpp>
#include <cppcoro/detail/remove_rvalue_reference.hpp>
namespace cppcoro
{
template<typename SCHEDULER>
struct schedule_on_transform
{
explicit schedule_on_transform(SCHEDULER& scheduler) noexcept
: scheduler(scheduler)
{}
SCHEDULER& scheduler;
};
template<typename SCHEDULER>
schedule_on_transform<SCHEDULER> schedule_on(SCHEDULER& scheduler)
{
return schedule_on_transform<SCHEDULER>{ scheduler };
}
template<typename T, typename SCHEDULER>
decltype(auto) operator|(T&& value, schedule_on_transform<SCHEDULER> transform)
{
return schedule_on(transform.scheduler, std::forward<T>(value));
}
template<typename SCHEDULER, typename AWAITABLE>
auto schedule_on(SCHEDULER& scheduler, AWAITABLE awaitable)
-> task<detail::remove_rvalue_reference_t<typename awaitable_traits<AWAITABLE>::await_result_t>>
{
co_await scheduler.schedule();
co_return co_await std::move(awaitable);
}
template<typename T, typename SCHEDULER>
async_generator<T> schedule_on(SCHEDULER& scheduler, async_generator<T> source)
{
// Transfer exection to the scheduler before the implicit calls to
// 'co_await begin()' or subsequent calls to `co_await iterator::operator++()`
// below. This ensures that all calls to the generator's coroutine_handle<>::resume()
// are executed on the execution context of the scheduler.
co_await scheduler.schedule();
const auto itEnd = source.end();
auto it = co_await source.begin();
while (it != itEnd)
{
co_yield *it;
co_await scheduler.schedule();
(void)co_await ++it;
}
}
}
#endif