Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion src/graph.cc
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,37 @@ bool DependencyScan::RecomputeDirty(Node* initial_node,
return true;
}

namespace {
class propagateDirty {
public:
propagateDirty(std::vector<Node*>* topLevelNodes)
: topLevelNodes_(topLevelNodes) {}

void process(Edge* edge);

private:
std::vector<Node*>* topLevelNodes_;
};

void propagateDirty::process(Edge* const edge) {
for (Node* const out : edge->outputs_) {
if (out->clean()) {
out->MarkDirty();
edge->outputs_ready_ = false;
if (out->out_edges().empty()) {
// add target to top level
topLevelNodes_->push_back(out);
continue;
}
for (Edge* outEdge : out->out_edges()) {
if (outEdge)
process(outEdge);
}
}
}
}
} // namespace

bool DependencyScan::RecomputeNodeDirty(Node* node, std::vector<Node*>* stack,
std::vector<Node*>* validation_nodes,
string* err) {
Expand Down Expand Up @@ -112,6 +143,7 @@ bool DependencyScan::RecomputeNodeDirty(Node* node, std::vector<Node*>* stack,
bool dirty = false;
edge->outputs_ready_ = true;
edge->deps_missing_ = false;
bool dyndepLoaded = false;

if (!edge->deps_loaded_) {
// This is our first encounter with this edge.
Expand All @@ -134,6 +166,8 @@ bool DependencyScan::RecomputeNodeDirty(Node* node, std::vector<Node*>* stack,
// The dyndep file is ready, so load it now.
if (!LoadDyndeps(edge->dyndep_, err))
return false;
else
dyndepLoaded = true;
}
}
}
Expand Down Expand Up @@ -202,8 +236,16 @@ bool DependencyScan::RecomputeNodeDirty(Node* node, std::vector<Node*>* stack,
// Finally, visit each output and update their dirty state if necessary.
for (vector<Node*>::iterator o = edge->outputs_.begin();
o != edge->outputs_.end(); ++o) {
if (dirty)
if (dirty) {
(*o)->MarkDirty();
if (dyndepLoaded) {
propagateDirty propagateDirtyDyndep(validation_nodes);
for (Edge* outedges : (*o)->out_edges())
propagateDirtyDyndep.process(outedges);
}
} else {
(*o)->MarkClean();
}
}

// If an edge is dirty, its outputs are normally not ready. (It's
Expand Down
25 changes: 20 additions & 5 deletions src/graph.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,12 @@ struct Node;
struct Pool;
struct State;

enum class DirtyState {
SPARE = 0,
DIRTY = 1,
CLEAN = 2,
};

/// Information about a node in the dependency graph: the file, whether
/// it's dirty, mtime, etc.
struct Node {
Expand All @@ -60,7 +66,7 @@ struct Node {
void ResetState() {
mtime_ = -1;
exists_ = ExistenceStatusUnknown;
dirty_ = false;
dirty_ = DirtyState::SPARE;
}

/// Mark the Node as already-stat()ed and missing.
Expand Down Expand Up @@ -90,9 +96,18 @@ struct Node {

TimeStamp mtime() const { return mtime_; }

bool dirty() const { return dirty_; }
void set_dirty(bool dirty) { dirty_ = dirty; }
void MarkDirty() { dirty_ = true; }
bool dirty() const { return dirty_ == DirtyState::DIRTY; }
void set_dirty(bool dirty) {
if (dirty) {
dirty_ = DirtyState::DIRTY;
} else if (dirty_ == DirtyState::DIRTY) {
dirty_ = DirtyState::CLEAN;
}
}
void MarkDirty() { dirty_ = DirtyState::DIRTY; }

bool clean() const { return dirty_ == DirtyState::CLEAN; }
void MarkClean() { dirty_ = DirtyState::CLEAN; }

bool dyndep_pending() const { return dyndep_pending_; }
void set_dyndep_pending(bool pending) { dyndep_pending_ = pending; }
Expand Down Expand Up @@ -144,7 +159,7 @@ struct Node {
/// Dirty is true when the underlying file is out-of-date.
/// But note that Edge::outputs_ready_ is also used in judging which
/// edges to build.
bool dirty_ = false;
DirtyState dirty_ = DirtyState::SPARE;

/// Store whether dyndep information is expected from this node but
/// has not yet been loaded.
Expand Down
Loading