| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library barback.phase; | 5 library barback.phase; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'asset_cascade.dart'; | 9 import 'asset_cascade.dart'; |
| 10 import 'asset_id.dart'; | 10 import 'asset_id.dart'; |
| (...skipping 18 matching lines...) Expand all Loading... |
| 29 /// | 29 /// |
| 30 /// Building can be interrupted between phases. For example, a source is added | 30 /// Building can be interrupted between phases. For example, a source is added |
| 31 /// which starts the background process. Sometime during, say, phase 2 (which | 31 /// which starts the background process. Sometime during, say, phase 2 (which |
| 32 /// is running asynchronously) that source is modified. When the process queue | 32 /// is running asynchronously) that source is modified. When the process queue |
| 33 /// goes to advance to phase 3, it will see that modification and start the | 33 /// goes to advance to phase 3, it will see that modification and start the |
| 34 /// waterfall from the beginning again. | 34 /// waterfall from the beginning again. |
| 35 class Phase { | 35 class Phase { |
| 36 /// The cascade that owns this phase. | 36 /// The cascade that owns this phase. |
| 37 final AssetCascade cascade; | 37 final AssetCascade cascade; |
| 38 | 38 |
| 39 /// A string describing the location of [this] in the transformer graph. |
| 40 final String _location; |
| 41 |
| 42 /// The index of [this] in its parent cascade or group. |
| 43 final int _index; |
| 44 |
| 39 /// The transformers that can access [inputs]. | 45 /// The transformers that can access [inputs]. |
| 40 /// | 46 /// |
| 41 /// Their outputs will be available to the next phase. | 47 /// Their outputs will be available to the next phase. |
| 42 final Set<Transformer> _transformers; | 48 final Set<Transformer> _transformers; |
| 43 | 49 |
| 44 /// The groups for this phase. | 50 /// The groups for this phase. |
| 45 final _groups = new Map<TransformerGroup, GroupRunner>(); | 51 final _groups = new Map<TransformerGroup, GroupRunner>(); |
| 46 | 52 |
| 47 /// The inputs for this phase. | 53 /// The inputs for this phase. |
| 48 /// | 54 /// |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 Set<AssetNode> get availableOutputs { | 110 Set<AssetNode> get availableOutputs { |
| 105 return _outputs.values | 111 return _outputs.values |
| 106 .map((output) => output.output) | 112 .map((output) => output.output) |
| 107 .where((node) => node.state.isAvailable) | 113 .where((node) => node.state.isAvailable) |
| 108 .toSet(); | 114 .toSet(); |
| 109 } | 115 } |
| 110 | 116 |
| 111 // TODO(nweiz): Rather than passing the cascade and the phase everywhere, | 117 // TODO(nweiz): Rather than passing the cascade and the phase everywhere, |
| 112 // create an interface that just exposes [getInput]. Emit errors via | 118 // create an interface that just exposes [getInput]. Emit errors via |
| 113 // [AssetNode]s. | 119 // [AssetNode]s. |
| 114 Phase(this.cascade, Iterable transformers) | 120 Phase(AssetCascade cascade, Iterable transformers, String location) |
| 121 : this._(cascade, transformers, location, 0); |
| 122 |
| 123 Phase._(this.cascade, Iterable transformers, this._location, this._index) |
| 115 : _transformers = transformers.where((op) => op is Transformer).toSet() { | 124 : _transformers = transformers.where((op) => op is Transformer).toSet() { |
| 116 _onDirtyPool.add(_onDirtyController.stream); | 125 _onDirtyPool.add(_onDirtyController.stream); |
| 117 | 126 |
| 118 for (var group in transformers.where((op) => op is TransformerGroup)) { | 127 for (var group in transformers.where((op) => op is TransformerGroup)) { |
| 119 var runner = new GroupRunner(cascade, group); | 128 var runner = new GroupRunner(cascade, group, "$_location.$_index"); |
| 120 _groups[group] = runner; | 129 _groups[group] = runner; |
| 121 _onDirtyPool.add(runner.onDirty); | 130 _onDirtyPool.add(runner.onDirty); |
| 122 _onLogPool.add(runner.onLog); | 131 _onLogPool.add(runner.onLog); |
| 123 } | 132 } |
| 124 } | 133 } |
| 125 | 134 |
| 126 /// Adds a new asset as an input for this phase. | 135 /// Adds a new asset as an input for this phase. |
| 127 /// | 136 /// |
| 128 /// [node] doesn't have to be [AssetState.AVAILABLE]. Once it is, the phase | 137 /// [node] doesn't have to be [AssetState.AVAILABLE]. Once it is, the phase |
| 129 /// will automatically begin determining which transforms can consume it as a | 138 /// will automatically begin determining which transforms can consume it as a |
| (...skipping 11 matching lines...) Expand all Loading... |
| 141 var forwarder = new PhaseForwarder(_groups.length + 1); | 150 var forwarder = new PhaseForwarder(_groups.length + 1); |
| 142 _forwarders[node.id] = forwarder; | 151 _forwarders[node.id] = forwarder; |
| 143 forwarder.onForwarding.listen((asset) { | 152 forwarder.onForwarding.listen((asset) { |
| 144 _addOutput(asset); | 153 _addOutput(asset); |
| 145 | 154 |
| 146 var exception = _outputs[asset.id].collisionException; | 155 var exception = _outputs[asset.id].collisionException; |
| 147 if (exception != null) cascade.reportError(exception); | 156 if (exception != null) cascade.reportError(exception); |
| 148 }); | 157 }); |
| 149 | 158 |
| 150 _inputOrigins.add(node.origin); | 159 _inputOrigins.add(node.origin); |
| 151 var input = new PhaseInput(this, node, _transformers); | 160 var input = new PhaseInput(this, node, _transformers, "$_location.$_index"); |
| 152 _inputs[node.id] = input; | 161 _inputs[node.id] = input; |
| 153 input.input.whenRemoved(() { | 162 input.input.whenRemoved(() { |
| 154 _inputOrigins.remove(node.origin); | 163 _inputOrigins.remove(node.origin); |
| 155 _inputs.remove(node.id); | 164 _inputs.remove(node.id); |
| 156 _forwarders.remove(node.id).remove(); | 165 _forwarders.remove(node.id).remove(); |
| 157 }); | 166 }); |
| 158 _onDirtyPool.add(input.onDirty); | 167 _onDirtyPool.add(input.onDirty); |
| 159 _onDirtyController.add(null); | 168 _onDirtyController.add(null); |
| 160 _onLogPool.add(input.onLog); | 169 _onLogPool.add(input.onLog); |
| 161 | 170 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 } | 207 } |
| 199 | 208 |
| 200 var newGroups = transformers.where((op) => op is TransformerGroup) | 209 var newGroups = transformers.where((op) => op is TransformerGroup) |
| 201 .toSet(); | 210 .toSet(); |
| 202 var oldGroups = _groups.keys.toSet(); | 211 var oldGroups = _groups.keys.toSet(); |
| 203 for (var removed in oldGroups.difference(newGroups)) { | 212 for (var removed in oldGroups.difference(newGroups)) { |
| 204 _groups.remove(removed).remove(); | 213 _groups.remove(removed).remove(); |
| 205 } | 214 } |
| 206 | 215 |
| 207 for (var added in newGroups.difference(oldGroups)) { | 216 for (var added in newGroups.difference(oldGroups)) { |
| 208 var runner = new GroupRunner(cascade, added); | 217 var runner = new GroupRunner(cascade, added, "$_location.$_index"); |
| 209 _groups[added] = runner; | 218 _groups[added] = runner; |
| 210 _onDirtyPool.add(runner.onDirty); | 219 _onDirtyPool.add(runner.onDirty); |
| 211 _onLogPool.add(runner.onLog); | 220 _onLogPool.add(runner.onLog); |
| 212 for (var input in _inputs.values) { | 221 for (var input in _inputs.values) { |
| 213 runner.addInput(input.input); | 222 runner.addInput(input.input); |
| 214 } | 223 } |
| 215 } | 224 } |
| 216 | 225 |
| 217 for (var forwarder in _forwarders.values) { | 226 for (var forwarder in _forwarders.values) { |
| 218 forwarder.numChannels = _groups.length + 1; | 227 forwarder.numChannels = _groups.length + 1; |
| 219 } | 228 } |
| 220 } | 229 } |
| 221 | 230 |
| 222 /// Add a new phase after this one with [transformers]. | 231 /// Add a new phase after this one with [transformers]. |
| 223 /// | 232 /// |
| 224 /// This may only be called on a phase with no phase following it. | 233 /// This may only be called on a phase with no phase following it. |
| 225 Phase addPhase(Iterable transformers) { | 234 Phase addPhase(Iterable transformers) { |
| 226 assert(_next == null); | 235 assert(_next == null); |
| 227 _next = new Phase(cascade, transformers); | 236 _next = new Phase._(cascade, transformers, _location, _index + 1); |
| 228 for (var output in _outputs.values.toList()) { | 237 for (var output in _outputs.values.toList()) { |
| 229 // Remove [output]'s listeners because now they should get the asset from | 238 // Remove [output]'s listeners because now they should get the asset from |
| 230 // [_next], rather than this phase. Any transforms consuming [output] will | 239 // [_next], rather than this phase. Any transforms consuming [output] will |
| 231 // be re-run and will consume the output from the new final phase. | 240 // be re-run and will consume the output from the new final phase. |
| 232 output.removeListeners(); | 241 output.removeListeners(); |
| 233 } | 242 } |
| 234 return _next; | 243 return _next; |
| 235 } | 244 } |
| 236 | 245 |
| 237 /// Mark this phase as removed. | 246 /// Mark this phase as removed. |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 298 if (exception != null) cascade.reportError(exception); | 307 if (exception != null) cascade.reportError(exception); |
| 299 } | 308 } |
| 300 }); | 309 }); |
| 301 } | 310 } |
| 302 | 311 |
| 303 /// Add [asset] as an output of this phase. | 312 /// Add [asset] as an output of this phase. |
| 304 void _addOutput(AssetNode asset) { | 313 void _addOutput(AssetNode asset) { |
| 305 if (_outputs.containsKey(asset.id)) { | 314 if (_outputs.containsKey(asset.id)) { |
| 306 _outputs[asset.id].add(asset); | 315 _outputs[asset.id].add(asset); |
| 307 } else { | 316 } else { |
| 308 _outputs[asset.id] = new PhaseOutput(this, asset); | 317 _outputs[asset.id] = new PhaseOutput(this, asset, "$_location.$_index"); |
| 309 _outputs[asset.id].onAsset.listen((output) { | 318 _outputs[asset.id].onAsset.listen((output) { |
| 310 if (_next != null) _next.addInput(output); | 319 if (_next != null) _next.addInput(output); |
| 311 }, onDone: () => _outputs.remove(asset.id)); | 320 }, onDone: () => _outputs.remove(asset.id)); |
| 312 if (_next != null) _next.addInput(_outputs[asset.id].output); | 321 if (_next != null) _next.addInput(_outputs[asset.id].output); |
| 313 } | 322 } |
| 314 } | 323 } |
| 324 |
| 325 String toString() => "phase $_location.$_index"; |
| 315 } | 326 } |
| OLD | NEW |