77
88namespace rime {
99
10+ enum DependencyPriority {
11+ kPendingChild = 0 ,
12+ kInclude = 1 ,
13+ kPatch = 2 ,
14+ };
15+
1016struct Dependency {
1117 an<ConfigItemRef> target;
1218
13- virtual bool blocking () const = 0;
19+ virtual DependencyPriority priority () const = 0;
20+ bool blocking () const {
21+ return priority () > kPendingChild ;
22+ }
1423 virtual string repr () const = 0;
1524 virtual bool Resolve (ConfigCompiler* compiler) = 0;
1625};
1726
1827template <class StreamT >
1928StreamT& operator << (StreamT& stream, const Dependency& dep) {
20- return stream << dep.repr () << (dep. blocking () ? " (blocking) " : " " ) ;
29+ return stream << dep.repr ();
2130}
2231
2332struct PendingChild : Dependency {
@@ -27,8 +36,8 @@ struct PendingChild : Dependency {
2736 PendingChild (const string& path, const an<ConfigItemRef>& ref)
2837 : child_path(path), child_ref(ref) {
2938 }
30- bool blocking () const override {
31- return false ;
39+ DependencyPriority priority () const override {
40+ return kPendingChild ;
3241 }
3342 string repr () const override {
3443 return " PendingChild(" + child_path + " )" ;
@@ -48,8 +57,8 @@ StreamT& operator<< (StreamT& stream, const Reference& reference) {
4857struct IncludeReference : Dependency {
4958 IncludeReference (const Reference& r) : reference(r) {
5059 }
51- bool blocking () const override {
52- return true ;
60+ DependencyPriority priority () const override {
61+ return kInclude ;
5362 }
5463 string repr () const override {
5564 return " Include(" + reference.repr () + " )" ;
@@ -62,8 +71,8 @@ struct IncludeReference : Dependency {
6271struct PatchReference : Dependency {
6372 PatchReference (const Reference& r) : reference(r) {
6473 }
65- bool blocking () const override {
66- return true ;
74+ DependencyPriority priority () const override {
75+ return kPatch ;
6776 }
6877 string repr () const override {
6978 return " Patch(" + reference.repr () + " )" ;
@@ -78,8 +87,8 @@ struct PatchLiteral : Dependency {
7887
7988 PatchLiteral (an<ConfigMap> map) : patch(map) {
8089 }
81- bool blocking () const override {
82- return true ;
90+ DependencyPriority priority () const override {
91+ return kPatch ;
8392 }
8493 string repr () const override {
8594 return " Patch(<literal>)" ;
@@ -91,7 +100,7 @@ struct ConfigDependencyGraph {
91100 map<string, of<ConfigResource>> resources;
92101 vector<of<ConfigItemRef>> node_stack;
93102 vector<string> key_stack;
94- map<string, list <of<Dependency>>> deps;
103+ map<string, vector <of<Dependency>>> deps;
95104
96105 void Add (an<Dependency> dependency);
97106
@@ -162,21 +171,34 @@ bool PatchLiteral::Resolve(ConfigCompiler* compiler) {
162171 return success;
163172}
164173
174+ static void InsertByPriority (vector<of<Dependency>>& list,
175+ const an<Dependency>& value) {
176+ auto upper = std::upper_bound (
177+ list.begin (), list.end (), value,
178+ [](const an<Dependency>& lhs, const an<Dependency>& rhs) {
179+ return lhs->priority () < rhs->priority ();
180+ });
181+ list.insert (upper, value);
182+ }
183+
165184void ConfigDependencyGraph::Add (an<Dependency> dependency) {
166- LOG (INFO) << " ConfigDependencyGraph::Add(), node_stack.size() = " << node_stack.size ();
185+ LOG (INFO) << " ConfigDependencyGraph::Add(), node_stack.size() = "
186+ << node_stack.size ();
167187 if (node_stack.empty ()) return ;
168188 const auto & target = node_stack.back ();
169189 dependency->target = target;
170190 auto target_path = ConfigData::JoinPath (key_stack);
171191 auto & target_deps = deps[target_path];
172192 bool target_was_pending = !target_deps.empty ();
173- target_deps.push_back (dependency);
174- LOG (INFO) << " target_path = " << target_path << " , #deps = " << target_deps.size ();
193+ InsertByPriority (target_deps, dependency);
194+ LOG (INFO) << " target_path = " << target_path
195+ << " , #deps = " << target_deps.size ();
175196 if (target_was_pending || // so was all ancestors
176197 key_stack.size () == 1 ) { // this is the progenitor
177198 return ;
178199 }
179- // The current pending node becomes a prioritized dependency of parent node
200+ // The current pending node becomes a prioritized non-blocking dependency of
201+ // its parent node; spread the pending state to its non-pending ancestors
180202 auto keys = key_stack;
181203 for (auto child = node_stack.rbegin (); child != node_stack.rend (); ++child) {
182204 auto last_key = keys.back ();
@@ -185,8 +207,10 @@ void ConfigDependencyGraph::Add(an<Dependency> dependency) {
185207 auto & parent_deps = deps[parent_path];
186208 bool parent_was_pending = !parent_deps.empty ();
187209 // Pending children should be resolved before applying __include or __patch
188- parent_deps.push_front (New<PendingChild>(parent_path + " /" + last_key, *child));
189- LOG (INFO) << " parent_path = " << parent_path << " , #deps = " << parent_deps.size ();
210+ InsertByPriority (parent_deps,
211+ New<PendingChild>(parent_path + " /" + last_key, *child));
212+ LOG (INFO) << " parent_path = " << parent_path
213+ << " , #deps = " << parent_deps.size ();
190214 if (parent_was_pending || // so was all ancestors
191215 keys.size () == 1 ) { // this parent is the progenitor
192216 return ;
@@ -418,10 +442,10 @@ bool ConfigCompiler::ResolveDependencies(const string& path) {
418442 auto & deps = graph_->deps [path];
419443 for (auto iter = deps.begin (); iter != deps.end (); ) {
420444 if (!(*iter)->Resolve (this )) {
421- LOG (ERROR) << " unesolved dependency:" << **iter;
445+ LOG (ERROR) << " unresolved dependency: " << **iter;
422446 return false ;
423447 }
424- LOG (INFO) << " resolved " << **iter;
448+ LOG (INFO) << " resolved: " << **iter;
425449 iter = deps.erase (iter);
426450 }
427451 LOG (INFO) << " all dependencies resolved." ;
0 commit comments