split out coroutine stuff into make_task
parent
097722b1ed
commit
d4037f9c1d
|
@ -212,6 +212,37 @@ private:
|
||||||
bool p_action = false;
|
bool p_action = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct make_task {
|
||||||
|
make_task() = delete;
|
||||||
|
make_task(
|
||||||
|
string_range target, std::vector<std::string> deps, make_rule &rl
|
||||||
|
) {
|
||||||
|
p_coro = std::make_unique<coroutine<void()>>(
|
||||||
|
[target, deps = std::move(deps), &rl](auto) {
|
||||||
|
std::vector<string_range> rdeps;
|
||||||
|
for (auto &s: deps) {
|
||||||
|
rdeps.push_back(s);
|
||||||
|
}
|
||||||
|
rl.call(target, iterator_range<string_range *>(
|
||||||
|
rdeps.data(), rdeps.data() + rdeps.size()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
);
|
||||||
|
p_coro->resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool done() const {
|
||||||
|
return !*p_coro;
|
||||||
|
}
|
||||||
|
|
||||||
|
void resume() {
|
||||||
|
p_coro->resume();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unique_ptr<coroutine<void()>> p_coro{};
|
||||||
|
};
|
||||||
|
|
||||||
struct make {
|
struct make {
|
||||||
make(int threads = std::thread::hardware_concurrency()) {
|
make(int threads = std::thread::hardware_concurrency()) {
|
||||||
p_tpool.start(threads);
|
p_tpool.start(threads);
|
||||||
|
@ -264,8 +295,8 @@ private:
|
||||||
|
|
||||||
template<typename F>
|
template<typename F>
|
||||||
void wait_for(F func) {
|
void wait_for(F func) {
|
||||||
std::queue<std::unique_ptr<coroutine<void()>>> coros;
|
std::queue<make_task> tasks;
|
||||||
p_waiting.push(&coros);
|
p_waiting.push(&tasks);
|
||||||
try {
|
try {
|
||||||
func();
|
func();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
|
@ -273,35 +304,35 @@ private:
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
p_waiting.pop();
|
p_waiting.pop();
|
||||||
if (coros.empty()) {
|
if (tasks.empty()) {
|
||||||
/* nothing to wait for, so return */
|
/* nothing to wait for, so return */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/* cycle until coroutines are done */
|
/* cycle until tasks are done */
|
||||||
std::unique_lock<std::mutex> lk{p_mtx};
|
std::unique_lock<std::mutex> lk{p_mtx};
|
||||||
while (!p_avail) {
|
while (!p_avail) {
|
||||||
p_cond.wait(lk);
|
p_cond.wait(lk);
|
||||||
}
|
}
|
||||||
std::queue<std::unique_ptr<coroutine<void()>>> acoros;
|
std::queue<make_task> atasks;
|
||||||
while (!coros.empty()) {
|
while (!tasks.empty()) {
|
||||||
p_avail = false;
|
p_avail = false;
|
||||||
while (!coros.empty()) {
|
while (!tasks.empty()) {
|
||||||
try {
|
try {
|
||||||
auto c = std::move(coros.front());
|
auto t = std::move(tasks.front());
|
||||||
coros.pop();
|
tasks.pop();
|
||||||
c->resume();
|
t.resume();
|
||||||
if (*c) {
|
if (!t.done()) {
|
||||||
/* still not dead, re-push */
|
/* still not dead, re-push */
|
||||||
acoros.push(std::move(c));
|
atasks.push(std::move(t));
|
||||||
}
|
}
|
||||||
} catch (make_error const &) {
|
} catch (make_error const &) {
|
||||||
writeln("waiting for the remaining tasks to finish...");
|
writeln("waiting for the remaining tasks to finish...");
|
||||||
for (; !coros.empty(); coros.pop()) {
|
for (; !tasks.empty(); tasks.pop()) {
|
||||||
try {
|
try {
|
||||||
auto c = std::move(coros.front());
|
auto t = std::move(tasks.front());
|
||||||
coros.pop();
|
tasks.pop();
|
||||||
while (*c) {
|
while (!t.done()) {
|
||||||
c->resume();
|
t.resume();
|
||||||
}
|
}
|
||||||
} catch (make_error const &) {
|
} catch (make_error const &) {
|
||||||
/* no rethrow */
|
/* no rethrow */
|
||||||
|
@ -310,10 +341,10 @@ private:
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (acoros.empty()) {
|
if (atasks.empty()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
coros.swap(acoros);
|
tasks.swap(atasks);
|
||||||
/* so we're not busylooping */
|
/* so we're not busylooping */
|
||||||
while (!p_avail) {
|
while (!p_avail) {
|
||||||
p_cond.wait(lk);
|
p_cond.wait(lk);
|
||||||
|
@ -361,20 +392,9 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (rl && (rl->action() || detail::check_exec(tname, rdeps))) {
|
if (rl && (rl->action() || detail::check_exec(tname, rdeps))) {
|
||||||
auto coro = std::make_unique<coroutine<void()>>(
|
make_task t{tname, std::move(rdeps), *rl};
|
||||||
[tname, rdeps, rl](auto) {
|
if (!t.done()) {
|
||||||
std::vector<string_range> rdepsl;
|
p_waiting.top()->push(std::move(t));
|
||||||
for (auto &s: rdeps) {
|
|
||||||
rdepsl.push_back(s);
|
|
||||||
}
|
|
||||||
rl->call(tname, iterator_range<string_range *>(
|
|
||||||
rdepsl.data(), rdepsl.data() + rdepsl.size()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
);
|
|
||||||
coro->resume();
|
|
||||||
if (*coro) {
|
|
||||||
p_waiting.top()->push(std::move(coro));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -452,7 +472,7 @@ private:
|
||||||
|
|
||||||
std::mutex p_mtx{};
|
std::mutex p_mtx{};
|
||||||
std::condition_variable p_cond{};
|
std::condition_variable p_cond{};
|
||||||
std::stack<std::queue<std::unique_ptr<coroutine<void()>>> *> p_waiting{};
|
std::stack<std::queue<make_task> *> p_waiting{};
|
||||||
bool p_avail = false;
|
bool p_avail = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue