#include "DepNode.h" #include #include #include #include "parallel.h" #include "logger.h" static void maybeAddStrings( std::unordered_set &set, const std::vector &vec, std::vector &out) { for (auto &str: vec) { auto pair = set.emplace(str); bool inserted = pair.second; if (inserted) { out.push_back(str); } } } void DepNode::addChild(std::shared_ptr node) { deps_.push_back(std::move(node)); } bool DepNode::haveDepsChanged(const std::string &outDir) { auto it = deps_.begin(); bool changed = false; int workers = 0; std::mutex mut; std::condition_variable cond; std::unique_lock lock(mut, std::defer_lock); while (it != deps_.end()) { lock.lock(); if (changed) { cond.wait(lock, [&] { return workers == 0; }); return true; } workers += 1; lock.unlock(); parallel::run([&, it] { bool ch = (*it)->hasChanged(outDir); std::unique_lock lock(mut); workers -= 1; if (ch) { changed = true; } lock.unlock(); cond.notify_one(); }); it = ++it; } lock.lock(); cond.wait(lock, [&] { return workers == 0; }); return changed; } bool DepNode::hasChanged(const std::string &outDir) { std::lock_guard lock(mut_); if (was_rebuilt_) { return true; } if (has_changed_ == TriState::TRUE) { return true; } else if (has_changed_ == TriState::FALSE) { return false; } else { bool changed = checkHasChanged(outDir); if (!changed) { changed = haveDepsChanged(outDir); } if (changed) { has_changed_ = TriState::TRUE; return true; } else { has_changed_ = TriState::FALSE; return false; } } } void DepNode::build(const std::string &outDir) { bool changed = hasChanged(outDir); std::lock_guard lock(mut_);\ if (!was_rebuilt_ && changed) { int workers = 0; std::mutex mut; std::condition_variable cond; std::unique_lock lock(mut, std::defer_lock); for (auto &dep: deps_) { if (dep->hasChanged(outDir)) { lock.lock(); workers += 1; lock.unlock(); parallel::run([&] { dep->build(outDir); std::unique_lock lock(mut); workers -= 1; lock.unlock(); cond.notify_one(); }); } } lock.lock(); cond.wait(lock, [&] { return workers == 0; }); doBuild(outDir); was_rebuilt_ = true; } } std::vector DepNode::publicLDFlags(const std::string &outDir) { std::unordered_set set; std::vector flags; maybeAddStrings(set, getPublicLDFlags(outDir), flags); for (auto &dep: deps_) { maybeAddStrings(set, dep->publicLDFlags(outDir), flags); } return flags; } std::vector DepNode::publicLDLibs(const std::string &outDir) { std::unordered_set set; std::vector libs; maybeAddStrings(set, getPublicLDLibs(outDir), libs); for (auto &dep: deps_) { maybeAddStrings(set, dep->publicLDLibs(outDir), libs); } return libs; } std::vector DepNode::publicObjects(const std::string &outDir) { std::vector objs = getPublicObjects(outDir);; for (auto &dep: deps_) { for (auto &obj: dep->publicObjects(outDir)) { objs.push_back(obj); } } return objs; }