Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: pkg/barback/lib/src/asset_node.dart

Issue 36463002: Fix a synchrony bug in barback. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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.asset_node; 5 library barback.asset_node;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'asset.dart'; 9 import 'asset.dart';
10 import 'asset_id.dart'; 10 import 'asset_id.dart';
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 /// or removed, the appropriate portion of the asset graph is dirtied before 55 /// or removed, the appropriate portion of the asset graph is dirtied before
56 /// any [Barback.getAssetById] calls emit newly-incorrect values. 56 /// any [Barback.getAssetById] calls emit newly-incorrect values.
57 Stream<AssetState> get onStateChange => _stateChangeController.stream; 57 Stream<AssetState> get onStateChange => _stateChangeController.stream;
58 58
59 /// This is synchronous so that a source being updated will always be 59 /// This is synchronous so that a source being updated will always be
60 /// propagated through the build graph before anything that depends on it is 60 /// propagated through the build graph before anything that depends on it is
61 /// requested. 61 /// requested.
62 final _stateChangeController = 62 final _stateChangeController =
63 new StreamController<AssetState>.broadcast(sync: true); 63 new StreamController<AssetState>.broadcast(sync: true);
64 64
65 /// Returns a Future that completes when the node's asset is available. 65 /// Calls [callback] when the node's asset is available.
66 /// 66 ///
67 /// If the asset is currently available, this completes synchronously to 67 /// If the asset is currently available, this calls [callback] synchronously
68 /// ensure that the asset is still available in the [Future.then] callback. 68 /// to ensure that the asset is still available.
69 /// 69 ///
70 /// If the asset is removed before becoming available, this will throw an 70 /// The return value of [callback] is piped to the returned Future. If the
71 /// [AssetNotFoundException]. 71 /// asset is removed before becoming available, the returned future will throw
72 Future<Asset> get whenAvailable { 72 /// an [AssetNotFoundException].
73 return _waitForState((state) => state.isAvailable || state.isRemoved) 73 Future whenAvailable(callback(Asset asset)) {
74 .then((state) { 74 return _waitForState((state) => state.isAvailable || state.isRemoved,
75 (state) {
75 if (state.isRemoved) throw new AssetNotFoundException(id); 76 if (state.isRemoved) throw new AssetNotFoundException(id);
76 return asset; 77 return callback(asset);
77 }); 78 });
78 } 79 }
79 80
80 /// Returns a Future that completes when the node's asset is removed. 81 /// Calls [callback] when the node's asset is removed.
81 /// 82 ///
82 /// If the asset is already removed when this is called, it completes 83 /// If the asset is already removed when this is called, it calls [callback]
83 /// synchronously. 84 /// synchronously.
84 Future get whenRemoved => _waitForState((state) => state.isRemoved); 85 ///
86 /// The return value of [callback] is piped to the returned Future.
87 Future whenRemoved(callback()) =>
88 _waitForState((state) => state.isRemoved, (_) => callback());
85 89
86 /// Runs [callback] repeatedly until the node's asset has maintained the same 90 /// Runs [callback] repeatedly until the node's asset has maintained the same
87 /// value for the duration. 91 /// value for the duration.
88 /// 92 ///
89 /// This will run [callback] as soon as the asset is available (synchronously 93 /// This will run [callback] as soon as the asset is available (synchronously
90 /// if it's available immediately). If the [state] changes at all while 94 /// if it's available immediately). If the [state] changes at all while
91 /// waiting for the Future returned by [callback] to complete, it will be 95 /// waiting for the Future returned by [callback] to complete, it will be
92 /// re-run as soon as it completes and the asset is available again. This will 96 /// re-run as soon as it completes and the asset is available again. This will
93 /// continue until [state] doesn't change at all. 97 /// continue until [state] doesn't change at all.
94 /// 98 ///
95 /// If this asset is removed, this will throw an [AssetNotFoundException] as 99 /// If this asset is removed, this will throw an [AssetNotFoundException] as
96 /// soon as [callback]'s Future is finished running. 100 /// soon as [callback]'s Future is finished running.
97 Future tryUntilStable(Future callback(Asset asset)) { 101 Future tryUntilStable(Future callback(Asset asset)) {
98 return whenAvailable.then((asset) { 102 return whenAvailable((asset) {
99 var modifiedDuringCallback = false; 103 var modifiedDuringCallback = false;
100 var subscription; 104 var subscription;
101 subscription = onStateChange.listen((_) { 105 subscription = onStateChange.listen((_) {
102 modifiedDuringCallback = true; 106 modifiedDuringCallback = true;
103 subscription.cancel(); 107 subscription.cancel();
104 }); 108 });
105 109
106 return callback(asset).then((result) { 110 return callback(asset).then((result) {
107 subscription.cancel(); 111 subscription.cancel();
108 112
109 // If the asset was modified at all while running the callback, the 113 // If the asset was modified at all while running the callback, the
110 // result was invalid and we should try again. 114 // result was invalid and we should try again.
111 if (modifiedDuringCallback) return tryUntilStable(callback); 115 if (modifiedDuringCallback) return tryUntilStable(callback);
112 return result; 116 return result;
113 }); 117 });
114 }); 118 });
115 } 119 }
116 120
117 /// Returns a Future that completes as soon as the node is in a state that 121 /// Calls [callback] as soon as the node is in a state that matches [test].
118 /// matches [test].
119 /// 122 ///
120 /// The Future completes synchronously if this is already in such a state. 123 /// [callback] is called synchronously if this is already in such a state.
121 Future<AssetState> _waitForState(bool test(AssetState state)) { 124 ///
122 if (test(state)) return new Future.sync(() => state); 125 /// The return value of [callback] is piped to the returned Future.
123 return onStateChange.firstWhere(test); 126 Future _waitForState(bool test(AssetState state),
127 callback(AssetState state)) {
128 if (test(state)) return new Future.sync(() => callback(state));
129 return onStateChange.firstWhere(test).then((_) => callback(state));
124 } 130 }
125 131
126 AssetNode._(this.id, this._transform, this._origin) 132 AssetNode._(this.id, this._transform, this._origin)
127 : _state = AssetState.DIRTY; 133 : _state = AssetState.DIRTY;
128 134
129 AssetNode._available(Asset asset, this._transform, this._origin) 135 AssetNode._available(Asset asset, this._transform, this._origin)
130 : id = asset.id, 136 : id = asset.id,
131 _asset = asset, 137 _asset = asset,
132 _state = AssetState.AVAILABLE; 138 _state = AssetState.AVAILABLE;
133 } 139 }
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
218 224
219 /// Whether this state is [AssetState.DIRTY]. 225 /// Whether this state is [AssetState.DIRTY].
220 bool get isDirty => this == AssetState.DIRTY; 226 bool get isDirty => this == AssetState.DIRTY;
221 227
222 final String name; 228 final String name;
223 229
224 const AssetState._(this.name); 230 const AssetState._(this.name);
225 231
226 String toString() => name; 232 String toString() => name;
227 } 233 }
OLDNEW
« no previous file with comments | « no previous file | pkg/barback/lib/src/group_runner.dart » ('j') | pkg/barback/test/package_graph/repetition_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698