/** @addtogroup Build * @{ */ /** @file make_coroutine.hh * * @brief Coroutine integration for ostd::build::make. * * This file provides an implementation of coroutine-based make tasks, * allowing for seamless synchronous-looking build rules. * * @copyright See COPYING.md in the project tree for further information. */ #ifndef OSTD_BUILD_MAKE_COROUTINE_HH #define OSTD_BUILD_MAKE_COROUTINE_HH #include #include #include #include #include #include namespace ostd { namespace build { /** @addtogroup Build * @{ */ namespace detail { struct make_task_coro: make_task { make_task_coro() = delete; make_task_coro( string_range target, std::vector deps, make_rule &rl ): p_coro( [target, deps = std::move(deps), &rl](auto) mutable { rl.call(target, iterator_range( deps.data(), deps.data() + deps.size() )); } ) {} bool done() const { return !p_coro; } void resume() { p_coro.resume(); } std::shared_future add_task(std::future f) { for (;;) { auto fs = f.wait_for(std::chrono::seconds(0)); if (fs != std::future_status::ready) { /* keep yielding until ready */ auto &cc = static_cast &>( *coroutine_context::current() ); (coroutine::yield_type(cc))(); } else { break; } } /* maybe propagate exception */ f.get(); /* future is done, nothing to actually share */ return std::shared_future{}; } private: coroutine p_coro; }; } inline make_task *make_task_coroutine( string_range target, std::vector deps, make_rule &rl ) { return new detail::make_task_coro{target, std::move(deps), rl}; } /** @} */ } /* namespace build */ } /* namespace ostd */ #endif /** @} */