/////////////////////////////////////////////////////////////////////////////// // 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 #include #include #include #include namespace cppcoro { template struct schedule_on_transform { explicit schedule_on_transform(SCHEDULER& scheduler) noexcept : scheduler(scheduler) {} SCHEDULER& scheduler; }; template schedule_on_transform schedule_on(SCHEDULER& scheduler) { return schedule_on_transform{ scheduler }; } template decltype(auto) operator|(T&& value, schedule_on_transform transform) { return schedule_on(transform.scheduler, std::forward(value)); } template auto schedule_on(SCHEDULER& scheduler, AWAITABLE awaitable) -> task::await_result_t>> { co_await scheduler.schedule(); co_return co_await std::move(awaitable); } template async_generator schedule_on(SCHEDULER& scheduler, async_generator 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