initial parallel build support

master
Daniel Kolesa 2015-08-24 11:16:55 -07:00
parent 19fb1100f8
commit 87d34dede1
2 changed files with 81 additions and 9 deletions

81
main.cc
View File

@ -5,6 +5,7 @@
#include <ostd/types.hh>
#include <ostd/string.hh>
#include <ostd/vector.hh>
#include <ostd/atomic.hh>
#include <cubescript.hh>
@ -25,6 +26,55 @@ struct Rule {
ostd::Vector<Rule> rules;
struct RuleCounter;
ostd::Vector<RuleCounter *> counters;
struct RuleCounter {
RuleCounter(): cond(), mtx(), counter(0), result(0) {
counters.push(this);
}
void wait() {
mtx.lock();
while (counter)
cond.wait(mtx);
mtx.unlock();
}
void incr() {
mtx.lock();
++counter;
mtx.unlock();
}
void decr() {
mtx.lock();
if (!--counter) {
mtx.unlock();
cond.broadcast();
} else
mtx.unlock();
}
int wait_result(int ret) {
counters.pop();
if (ret)
return ret;
wait();
ret = result;
if (ret)
return ret;
return 0;
}
Cond cond;
Mutex mtx;
volatile int counter;
ostd::AtomicInt result;
};
ThreadPool tpool;
/* check funcs */
static bool ob_check_ts(ostd::ConstCharRange tname,
@ -283,9 +333,14 @@ struct ObState {
int exec_func(ostd::ConstCharRange tname,
const ostd::Vector<SubRule> &rlist) {
ostd::Vector<ostd::String> subdeps;
int r = exec_list(rlist, subdeps, tname);
/* new scope for early destruction */
{
RuleCounter depcnt;
int r = depcnt.wait_result(exec_list(rlist, subdeps, tname));
if (r)
return r;
}
if (ob_check_exec(tname, subdeps)) {
if (r) return r;
ostd::Uint32 *func = nullptr;
for (auto &sr: rlist.iter()) {
Rule &r = *sr.rule;
@ -404,8 +459,20 @@ int main(int argc, char **argv) {
}
}
tpool.init(os.jobs);
os.cs.add_command("shell", "C", [](cscript::CsState &cs, char *s) {
cs.result->set_int(system(s));
RuleCounter *cnt = counters.back();
cnt->incr();
char *dup = strdup(s);
tpool.push([cnt, dup]() {
int ret = system(dup);
free(dup);
if (ret && !cnt->result)
cnt->result = ret;
cnt->decr();
});
cs.result->set_int(0);
});
os.cs.add_command("rule", "sseN", [](cscript::CsState &, const char *tgt,
@ -436,5 +503,11 @@ int main(int argc, char **argv) {
if (rules.empty())
return os.error(1, "no targets");
return os.exec_rule((optind < argc) ? argv[optind] : "all");
RuleCounter maincnt;
int ret = os.exec_rule((optind < argc) ? argv[optind] : "all");
ret = maincnt.wait_result(ret);
if (ret)
return ret;
tpool.destroy();
return 0;
}

View File

@ -61,7 +61,7 @@ struct Task {
};
struct ThreadPool {
ThreadPool(ostd::Size size): size(size) {}
ThreadPool() {}
~ThreadPool() {
if (running) destroy();
@ -72,7 +72,7 @@ struct ThreadPool {
return nullptr;
}
bool init() {
bool init(ostd::Size size) {
running = true;
for (ostd::Size i = 0; i < size; ++i) {
pthread_t tid;
@ -88,9 +88,9 @@ struct ThreadPool {
running = false;
mtx.unlock();
cond.broadcast();
for (ostd::Size i = 0; i < size; ++i) {
for (pthread_t &tid: thrs.iter()) {
void *ret;
pthread_join(thrs[i], &ret);
pthread_join(tid, &ret);
cond.broadcast();
}
}
@ -127,7 +127,6 @@ struct ThreadPool {
}
private:
ostd::Size size;
Cond cond;
Mutex mtx;
ostd::Vector<pthread_t> thrs;