Chromium Code Reviews| Index: pkg/barback/lib/src/transform_node.dart |
| diff --git a/pkg/barback/lib/src/transform_node.dart b/pkg/barback/lib/src/transform_node.dart |
| index 2269344d5eb0a3b2620761bd636e3df2fe712932..1ea4fdb7e7cf92193496bf1e9c6da90d8b004b1f 100644 |
| --- a/pkg/barback/lib/src/transform_node.dart |
| +++ b/pkg/barback/lib/src/transform_node.dart |
| @@ -45,14 +45,25 @@ class TransformNode { |
| StreamSubscription<AssetNode> _phaseSubscription; |
| /// Whether [this] is dirty and still has more processing to do. |
| - bool get isDirty => _state != _State.NOT_PRIMARY && _state != _State.APPLIED; |
| + bool get isDirty => _state != _State.NOT_PRIMARY && |
| + _state != _State.APPLIED && _state != _State.DECLARED; |
| - /// Whether this transform is lazy and this transform has yet to be forced. |
| + /// Whether this transform is lazy. |
| /// |
| /// A transform being lazy is distinct from a transformer being lazy. A |
| /// transformer that's declaring but not lazy will have lazy transforms for |
| /// primary inputs that are themselves lazy. |
|
Bob Nystrom
2014/04/10 22:58:56
I think we should disambiguate these terms. How ab
nweiz
2014/04/11 00:47:59
Done.
|
| - bool _isLazy; |
| + final bool _isLazy; |
| + |
| + /// Whether this is a lazy transform waiting for [force] to be called to |
| + /// generate inputs. |
| + /// |
| + /// This defaults to `true` for lazy transforms and `false` otherwise. During |
| + /// or after running `isPrimary` or `declareOutputs`, this may become `false`, |
| + /// indicating that the transform has been forced and should generate outputs |
| + /// as soon as possible. It will only be set back to `true` if an input |
| + /// changes *after* `apply` has completed. |
| + bool _awaitingForce; |
|
Bob Nystrom
2014/04/10 22:58:56
This name is a bit confusing. How about "_deferred
nweiz
2014/04/11 00:47:59
That doesn't match your previous suggestion. You s
Bob Nystrom
2014/04/14 19:20:25
Ah, good point.
|
| /// The subscriptions to each input's [AssetNode.onStateChange] stream. |
| final _inputSubscriptions = new Map<AssetId, StreamSubscription>(); |
| @@ -100,7 +111,7 @@ class TransformNode { |
| final _onLogController = new StreamController<LogEntry>.broadcast(sync: true); |
| /// The current state of [this]. |
| - var _state = _State.COMPUTING_IS_PRIMARY; |
| + var _state = _State.DECLARING; |
| /// Whether [this] has been marked as removed. |
| bool get _isRemoved => _onAssetController.isClosed; |
| @@ -109,7 +120,7 @@ class TransformNode { |
| /// consumes the primary input. |
| /// |
| /// Defaults to `false`. This is not meaningful unless [_state] is |
| - /// [_State.APPLIED]. |
| + /// [_State.APPLIED] or [_State.DECLARED]. |
| bool _consumePrimary = false; |
| /// The set of output ids that [transformer] declared it would emit. |
| @@ -124,6 +135,8 @@ class TransformNode { |
| primary = primary, |
| _isLazy = transformer is LazyTransformer || |
| (transformer is DeclaringTransformer && primary.isLazy) { |
| + _awaitingForce = _isLazy; |
| + |
| _onLogPool.add(_onLogController.stream); |
| if (!_isLazy) primary.force(); |
| @@ -132,12 +145,15 @@ class TransformNode { |
| if (state.isRemoved) { |
| remove(); |
| } else { |
| + if (state.isDirty && !_isLazy) primary.force(); |
| _dirty(); |
| } |
| }); |
| _phaseSubscription = phase.previous.onAsset.listen((node) { |
| - if (_missingInputs.contains(node.id)) _dirty(); |
| + if (!_missingInputs.contains(node.id)) return; |
| + if (!_isLazy) node.force(); |
| + _dirty(); |
| }); |
| _isPrimary(); |
| @@ -172,11 +188,9 @@ class TransformNode { |
| /// If [transformer] is lazy, ensures that its concrete outputs will be |
| /// generated. |
| void force() { |
| - // TODO(nweiz): we might want to have a timeout after which, if the |
| - // transform's outputs have gone unused, we switch it back to lazy mode. |
| - if (!_isLazy) return; |
| + if (!_awaitingForce) return; |
| primary.force(); |
| - _isLazy = false; |
| + _awaitingForce = false; |
| _dirty(); |
| } |
| @@ -188,14 +202,23 @@ class TransformNode { |
| _emitPassThrough(); |
| return; |
| } |
| - if (_state == _State.COMPUTING_IS_PRIMARY || _isLazy) return; |
| + if (_state == _State.DECLARING || _awaitingForce) return; |
|
Bob Nystrom
2014/04/10 22:58:56
Add some documentation here about what the DECLARI
nweiz
2014/04/11 00:47:59
Done.
|
| + |
| + if (_state == _State.APPLIED && _isLazy) { |
| + for (var controller in _outputControllers.values) { |
| + controller.setLazy(force); |
| + } |
| + _state = _State.DECLARED; |
|
Bob Nystrom
2014/04/10 22:58:56
This could use some docs here. It isn't obvious wh
nweiz
2014/04/11 00:47:59
Done.
|
| + _awaitingForce = true; |
| + return; |
| + } |
| if (_passThroughController != null) _passThroughController.setDirty(); |
| for (var controller in _outputControllers.values) { |
| controller.setDirty(); |
| } |
| - if (_state == _State.APPLIED) { |
| + if (_state == _State.APPLIED || _state == _State.DECLARED) { |
| _apply(); |
| } else { |
| _state = _State.NEEDS_APPLY; |
| @@ -221,8 +244,8 @@ class TransformNode { |
| if (isPrimary) { |
| return _declareOutputs().then((_) { |
| if (_isRemoved) return; |
| - if (_isLazy) { |
| - _state = _State.APPLIED; |
| + if (_awaitingForce) { |
| + _state = _State.DECLARED; |
| _onDoneController.add(null); |
| } else { |
| _apply(); |
| @@ -262,7 +285,7 @@ class TransformNode { |
| if (!_declaredOutputs.contains(primary.id)) _emitPassThrough(); |
| for (var id in _declaredOutputs) { |
| - var controller = _isLazy |
| + var controller = _awaitingForce |
| ? new AssetNodeController.lazy(id, force, this) |
| : new AssetNodeController(id, this); |
| _outputControllers[id] = controller; |
| @@ -276,7 +299,7 @@ class TransformNode { |
| /// Applies this transform. |
| void _apply() { |
| - assert(!_isRemoved && !_isLazy); |
| + assert(!_isRemoved && !_awaitingForce); |
| // Clear input subscriptions here as well as in [_process] because [_apply] |
| // may be restarted independently if only a secondary input changes. |
| @@ -324,7 +347,10 @@ class TransformNode { |
| } |
| _inputSubscriptions.putIfAbsent(node.id, () { |
| - return node.onStateChange.listen((_) => _dirty()); |
| + return node.onStateChange.listen((state) { |
| + if (state.isDirty) node.force(); |
|
Bob Nystrom
2014/04/10 22:58:56
So if an input to this transform changes to a dirt
nweiz
2014/04/11 00:47:59
Removed, as per discussion.
|
| + _dirty(); |
| + }); |
| }); |
| return node.asset; |
| @@ -475,12 +501,22 @@ class TransformNode { |
| /// The enum of states that [TransformNode] can be in. |
| class _State { |
| - /// The transform is running [Transformer.isPrimary]. |
| + /// The transform is running [Transformer.isPrimary] followed by |
| + /// [DeclaringTransformer.declareOutputs] (for a [DeclaringTransformer]). |
| + /// |
| + /// This is the initial state of the transformer, and it will only occur once |
| + /// since [Transformer.isPrimary] and [DeclaringTransformer.declareOutputs] |
| + /// are independent of the contents of the primary input. Once the two methods |
| + /// finish running, this will transition to [NOT_PRIMARY] if the input isn't |
| + /// primary, [DECLARED] if the transform is lazy, and [APPLYING] otherwise. |
| + static final DECLARING = const _State._("computing isPrimary"); |
| + |
| + /// The transform is lazy and has run [DeclaringTransformer.declareOutputs] |
| + /// but hasn't yet been forced. |
| /// |
| - /// This is the initial state of the transformer. Once [Transformer.isPrimary] |
| - /// finishes running, this will transition to [APPLYING] if the input is |
| - /// primary, or [NOT_PRIMARY] if it's not. |
| - static final COMPUTING_IS_PRIMARY = const _State._("computing isPrimary"); |
| + /// This will transition to [APPLYING] when one of the outputs has been |
| + /// forced. |
| + static final DECLARED = const _State._("declared"); |
|
Bob Nystrom
2014/04/10 22:58:56
"DEFERRED"?
nweiz
2014/04/11 00:47:59
That would be confusing in light of your terminolo
|
| /// The transform is running [Transformer.apply]. |
| /// |
| @@ -503,7 +539,8 @@ class _State { |
| /// when [Transformer.declareOutputs] has been run but [Transformer.apply] has |
| /// not. |
| /// |
| - /// If an input changes, this will transition to [APPLYING]. |
| + /// If an input changes, this will transition to [DECLARED] if the transform |
| + /// is lazy and [APPLYING] otherwise. |
| static final APPLIED = const _State._("applied"); |
| /// The transform has finished running [Transformer.isPrimary], which returned |