1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef TOOLS_GN_ITEM_NODE_H_ 6 #define TOOLS_GN_ITEM_NODE_H_ 7 8 #include <map> 9 #include <vector> 10 11 #include "base/basictypes.h" 12 #include "base/callback.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "tools/gn/location.h" 15 16 class BuildSettings; 17 class Err; 18 class Item; 19 20 // Represents a node in the depdency tree. It references an Item which is 21 // the actual thing. 22 // 23 // The items and nodes are split apart so that the ItemTree can manipulate 24 // the dependencies one one thread while the Item itself is been modified on 25 // another. 26 class ItemNode { 27 public: 28 // The state of this node. As more of the load progresses, we'll move 29 // downward in this list toward the resolved state. 30 enum State { 31 // Another item has referenced this one by name, but we have not yet 32 // encountered its definition. 33 REFERENCED = 0, 34 35 // We've seen the definition of this item but have not requested that its 36 // dependencies be loaded. In non-greedy generation mode (see item_tree.h) 37 // some nodes will stay in this state forever as long as they're not needed 38 // for anything that is required. 39 DEFINED, 40 41 // The item has been defined and we've requested that all of the 42 // dependencies be loaded. Not all of the dependencies have been resolved, 43 // however, and we're still waiting on some build files to be run (or 44 // perhaps there are undefined dependencies). 45 PENDING_DEPS, 46 47 // All of this item's transitive dependencies have been found and 48 // resolved. 49 RESOLVED, 50 }; 51 52 // Stores a set of ItemNodes and the associated range that the dependency 53 // was added from. 54 typedef std::map<ItemNode*, LocationRange> ItemNodeMap; 55 56 // Takes ownership of the pointer. 57 // Initial state will be REFERENCED. 58 ItemNode(Item* i); 59 ~ItemNode(); 60 61 State state() const { return state_; } 62 63 // This closure will be executed when the item is resolved and it has the 64 // should_generate flag set. 65 void set_resolved_closure(const base::Closure& closure) { 66 resolved_closure_ = closure; 67 } 68 69 const Item* item() const { return item_.get(); } 70 Item* item() { return item_.get(); } 71 72 // True if this item should be generated. In greedy mode, this will alwyas 73 // be set. Otherwise, this bit will be "pushed" through the tree to 74 // generate the minimum set of targets required for some special base target. 75 // Initialized to false. 76 // 77 // If this item has been defined, setting this flag will schedule the load 78 // of dependent nodes and also set their should_generate bits. 79 bool should_generate() const { return should_generate_; } 80 bool SetShouldGenerate(const BuildSettings* build_settings, Err* err); 81 82 // Where this was created from, which might be when it was generated or 83 // when it was first referenced from another target. 84 const LocationRange& originally_referenced_from_here() const { 85 return originally_referenced_from_here_; 86 } 87 void set_originally_referenced_from_here(const LocationRange& r) { 88 originally_referenced_from_here_ = r; 89 } 90 91 // Where this was generated from. This will be empty for items that have 92 // been referenced but not generated. Note that this has to be one the 93 // ItemNode because it can be changing from multiple threads and we need 94 // to be sure that access is serialized. 95 const LocationRange& generated_from_here() const { 96 return generated_from_here_; 97 } 98 void set_generated_from_here(const LocationRange& r) { 99 generated_from_here_ = r; 100 } 101 102 const ItemNodeMap& direct_dependencies() const { 103 return direct_dependencies_; 104 } 105 const ItemNodeMap& unresolved_dependencies() const { 106 return unresolved_dependencies_; 107 } 108 109 bool AddDependency(const BuildSettings* build_settings, 110 const LocationRange& specified_from_here, 111 ItemNode* node, 112 Err* err); 113 114 // Removes the given dependency from the unresolved list. Does not do 115 // anything else to update waiters. 116 void MarkDirectDependencyResolved(ItemNode* node); 117 118 // Destructively retrieve the set of waiting nodes. 119 void SwapOutWaitingDependencySet(ItemNodeMap* out_map); 120 121 // Marks this item state as defined (see above). If the should generate 122 // flag is set, this will schedule a load of the dependencies and 123 // automatically transition to the PENDING_DEPS state. 124 bool SetDefined(const BuildSettings* build_settings, Err* err); 125 126 // Marks this item state as resolved (see above). 127 void SetResolved(); 128 129 private: 130 // Schedules loading the dependencies of this node. The current state must 131 // be DEFINED, and this call will transition the state to PENDING_DEPS. 132 // 133 // Requesting deps can fail. On failure returns false and sets the err. 134 bool ScheduleDepsLoad(const BuildSettings* build_settings, Err* err); 135 136 State state_; 137 scoped_ptr<Item> item_; 138 bool should_generate_; // See getter above. 139 140 LocationRange originally_referenced_from_here_; 141 LocationRange generated_from_here_; 142 143 // What to run when this item is resolved. 144 base::Closure resolved_closure_; 145 146 // Everything this item directly depends on. 147 ItemNodeMap direct_dependencies_; 148 149 // Unresolved things this item directly depends on. 150 ItemNodeMap unresolved_dependencies_; 151 152 // These items are waiting on us to be resolved before they can be 153 // resolved. This is the backpointer for unresolved_dependencies_. 154 ItemNodeMap waiting_on_resolution_; 155 156 DISALLOW_COPY_AND_ASSIGN(ItemNode); 157 }; 158 159 #endif // TOOLS_GN_ITEM_NODE_H_ 160