From 8c40f335a7dba79922e461c1a3899c0c6a5b0580 Mon Sep 17 00:00:00 2001 From: q66 Date: Mon, 23 Apr 2018 22:33:37 +0200 Subject: [PATCH] add make_task_simple that does not use coroutines --- ostd/build/make.hh | 81 +++++++++++++++++++++++++++++++----- ostd/build/make_coroutine.hh | 7 +++- 2 files changed, 77 insertions(+), 11 deletions(-) diff --git a/ostd/build/make.hh b/ostd/build/make.hh index e1f7121..c22f4aa 100644 --- a/ostd/build/make.hh +++ b/ostd/build/make.hh @@ -218,9 +218,68 @@ struct make_task { virtual bool done() const = 0; virtual void resume() = 0; - virtual void add_task(std::future f) = 0; + virtual std::shared_future add_task(std::future f) = 0; }; +namespace detail { + struct make_task_simple: make_task { + make_task_simple() = delete; + + make_task_simple( + string_range target, std::vector deps, make_rule &rl + ): p_body( + [target, deps = std::move(deps), &rl]() mutable { + rl.call(target, iterator_range( + deps.data(), deps.data() + deps.size() + )); + } + ) {} + + bool done() const { + return p_futures.empty(); + } + + void resume() { + if (p_body) { + std::exchange(p_body, nullptr)(); + } + /* go over futures and erase those that are done */ + for (auto it = p_futures.begin(); it != p_futures.end();) { + auto fs = it->wait_for(std::chrono::seconds(0)); + if (fs == std::future_status::ready) { + /* maybe propagate exception */ + auto f = std::move(*it); + it = p_futures.erase(it); + try { + f.get(); + } catch (...) { + p_futures.clear(); + throw; + } + continue; + } + ++it; + } + } + + std::shared_future add_task(std::future f) { + auto sh = f.share(); + p_futures.push_back(sh); + return sh; + } + + private: + std::function p_body; + std::list> p_futures{}; + }; +} + +inline make_task *make_task_simple( + string_range target, std::vector deps, make_rule &rl +) { + return new detail::make_task_simple{target, std::move(deps), rl}; +} + struct make { using task_factory = std::function< make_task *(string_range, std::vector, make_rule &) @@ -238,15 +297,17 @@ struct make { }); } - void push_task(std::function func) { - p_current->add_task(p_tpool.push([func = std::move(func), this]() { - func(); - { - std::lock_guard l{p_mtx}; - p_avail = true; - } - p_cond.notify_one(); - })); + std::shared_future push_task(std::function func) { + return p_current->add_task( + p_tpool.push([func = std::move(func), this]() { + func(); + { + std::lock_guard l{p_mtx}; + p_avail = true; + } + p_cond.notify_one(); + }) + ); } make_rule &rule(string_range tgt) { diff --git a/ostd/build/make_coroutine.hh b/ostd/build/make_coroutine.hh index 718121b..e246939 100644 --- a/ostd/build/make_coroutine.hh +++ b/ostd/build/make_coroutine.hh @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -51,7 +52,7 @@ namespace detail { p_coro.resume(); } - void add_task(std::future f) { + std::shared_future add_task(std::future f) { for (;;) { auto fs = f.wait_for(std::chrono::seconds(0)); if (fs != std::future_status::ready) { @@ -64,6 +65,10 @@ namespace detail { break; } } + /* maybe propagate exception */ + f.get(); + /* future is done, nothing to actually share */ + return std::shared_future{}; } private: