summaryrefslogtreecommitdiffstats
path: root/tools/gn/item_node.h
blob: dbee141b7373593091a93aa6ac0a8250e0634021 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef TOOLS_GN_ITEM_NODE_H_
#define TOOLS_GN_ITEM_NODE_H_

#include <map>
#include <vector>

#include "base/basictypes.h"
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "tools/gn/location.h"

class BuildSettings;
class Err;
class Item;

// Represents a node in the depdency tree. It references an Item which is
// the actual thing.
//
// The items and nodes are split apart so that the ItemTree can manipulate
// the dependencies one one thread while the Item itself is been modified on
// another.
class ItemNode {
 public:
  // The state of this node. As more of the load progresses, we'll move
  // downward in this list toward the resolved state.
  enum State {
    // Another item has referenced this one by name, but we have not yet
    // encountered its definition.
    REFERENCED = 0,

    // We've seen the definition of this item but have not requested that its
    // dependencies be loaded. In non-greedy generation mode (see item_tree.h)
    // some nodes will stay in this state forever as long as they're not needed
    // for anything that is required.
    DEFINED,

    // The item has been defined and we've requested that all of the
    // dependencies be loaded. Not all of the dependencies have been resolved,
    // however, and we're still waiting on some build files to be run (or
    // perhaps there are undefined dependencies).
    PENDING_DEPS,

    // All of this item's transitive dependencies have been found and
    // resolved.
    RESOLVED,
  };

  // Stores a set of ItemNodes and the associated range that the dependency
  // was added from.
  typedef std::map<ItemNode*, LocationRange> ItemNodeMap;

  // Takes ownership of the pointer.
  // Initial state will be REFERENCED.
  ItemNode(Item* i);
  ~ItemNode();

  State state() const { return state_; }

  // This closure will be executed when the item is resolved and it has the
  // should_generate flag set.
  void set_resolved_closure(const base::Closure& closure) {
    resolved_closure_ = closure;
  }

  const Item* item() const { return item_.get(); }
  Item* item() { return item_.get(); }

  // True if this item should be generated. In greedy mode, this will alwyas
  // be set. Otherwise, this bit will be "pushed" through the tree to
  // generate the minimum set of targets required for some special base target.
  // Initialized to false.
  //
  // If this item has been defined, setting this flag will schedule the load
  // of dependent nodes and also set their should_generate bits.
  bool should_generate() const { return should_generate_; }
  bool SetShouldGenerate(const BuildSettings* build_settings, Err* err);

  // Where this was created from, which might be when it was generated or
  // when it was first referenced from another target.
  const LocationRange& originally_referenced_from_here() const {
    return originally_referenced_from_here_;
  }
  void set_originally_referenced_from_here(const LocationRange& r) {
    originally_referenced_from_here_ = r;
  }

  // Where this was generated from. This will be empty for items that have
  // been referenced but not generated. Note that this has to be one the
  // ItemNode because it can be changing from multiple threads and we need
  // to be sure that access is serialized.
  const LocationRange& generated_from_here() const {
    return generated_from_here_;
  }
  void set_generated_from_here(const LocationRange& r) {
    generated_from_here_ = r;
  }

  const ItemNodeMap& direct_dependencies() const {
    return direct_dependencies_;
  }
  const ItemNodeMap& unresolved_dependencies() const {
    return unresolved_dependencies_;
  }

  bool AddDependency(const BuildSettings* build_settings,
                     const LocationRange& specified_from_here,
                     ItemNode* node,
                     Err* err);

  // Removes the given dependency from the unresolved list. Does not do
  // anything else to update waiters.
  void MarkDirectDependencyResolved(ItemNode* node);

  // Destructively retrieve the set of waiting nodes.
  void SwapOutWaitingDependencySet(ItemNodeMap* out_map);

  // Marks this item state as defined (see above). If the should generate
  // flag is set, this will schedule a load of the dependencies and
  // automatically transition to the PENDING_DEPS state.
  bool SetDefined(const BuildSettings* build_settings, Err* err);

  // Marks this item state as resolved (see above).
  void SetResolved();

 private:
  // Schedules loading the dependencies of this node. The current state must
  // be DEFINED, and this call will transition the state to PENDING_DEPS.
  //
  // Requesting deps can fail. On failure returns false and sets the err.
  bool ScheduleDepsLoad(const BuildSettings* build_settings, Err* err);

  State state_;
  scoped_ptr<Item> item_;
  bool should_generate_;  // See getter above.

  LocationRange originally_referenced_from_here_;
  LocationRange generated_from_here_;

  // What to run when this item is resolved.
  base::Closure resolved_closure_;

  // Everything this item directly depends on.
  ItemNodeMap direct_dependencies_;

  // Unresolved things this item directly depends on.
  ItemNodeMap unresolved_dependencies_;

  // These items are waiting on us to be resolved before they can be
  // resolved. This is the backpointer for unresolved_dependencies_.
  ItemNodeMap waiting_on_resolution_;

  DISALLOW_COPY_AND_ASSIGN(ItemNode);
};

#endif  // TOOLS_GN_ITEM_NODE_H_