Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 async.future_group; | 5 library async.future_group; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 /// A collection of futures waits until all added [Future]s complete. | 9 /// A collection of futures waits until all added [Future]s complete. |
| 10 /// | 10 /// |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 var _closed = false; | 28 var _closed = false; |
| 29 | 29 |
| 30 /// The future that fires once [close] has been called and all futures in the | 30 /// The future that fires once [close] has been called and all futures in the |
| 31 /// group have completed. | 31 /// group have completed. |
| 32 /// | 32 /// |
| 33 /// This will also complete with an error if any of the futures in the group | 33 /// This will also complete with an error if any of the futures in the group |
| 34 /// fails, regardless of whether [close] was called. | 34 /// fails, regardless of whether [close] was called. |
| 35 Future<List<T>> get future => _completer.future; | 35 Future<List<T>> get future => _completer.future; |
| 36 final _completer = new Completer<List<T>>(); | 36 final _completer = new Completer<List<T>>(); |
| 37 | 37 |
| 38 /// Whether this group is waiting on any futures. | |
| 39 bool get isIdle => _pending == 0; | |
| 40 | |
| 41 /// A broadcast stream that emits a `null` event whenever the last pending | |
| 42 /// future in this group completes. | |
| 43 /// | |
| 44 /// Once this group isn't waiting on any futures *and* [close] has been | |
| 45 /// called, this stream will close. | |
| 46 Stream get onIdle => _onIdleController.stream; | |
| 47 final _onIdleController = new StreamController.broadcast(sync: true); | |
|
Lasse Reichstein Nielsen
2015/07/02 09:18:35
Could it be worth it to only create this controlle
nweiz
2015/07/06 20:23:18
Done.
| |
| 48 | |
| 38 /// The values emitted by the futures that have been added to the group, in | 49 /// The values emitted by the futures that have been added to the group, in |
| 39 /// the order they were added. | 50 /// the order they were added. |
| 40 /// | 51 /// |
| 41 /// The slots for futures that haven't completed yet are `null`. | 52 /// The slots for futures that haven't completed yet are `null`. |
| 42 final _values = new List<T>(); | 53 final _values = new List<T>(); |
| 43 | 54 |
| 44 /// Wait for [task] to complete. | 55 /// Wait for [task] to complete. |
| 45 void add(Future<T> task) { | 56 void add(Future<T> task) { |
| 46 if (_closed) throw new StateError("The FutureGroup is closed."); | 57 if (_closed) throw new StateError("The FutureGroup is closed."); |
| 47 | 58 |
| 48 // Ensure that future values are put into [values] in the same order they're | 59 // Ensure that future values are put into [values] in the same order they're |
| 49 // added to the group by pre-allocating a slot for them and recording its | 60 // added to the group by pre-allocating a slot for them and recording its |
| 50 // index. | 61 // index. |
| 51 var index = _values.length; | 62 var index = _values.length; |
| 52 _values.add(null); | 63 _values.add(null); |
| 53 | 64 |
| 54 _pending++; | 65 _pending++; |
| 55 task.then((value) { | 66 task.then((value) { |
| 56 if (_completer.isCompleted) return; | 67 if (_completer.isCompleted) return; |
| 57 | 68 |
| 58 _pending--; | 69 _pending--; |
| 59 _values[index] = value; | 70 _values[index] = value; |
| 60 | 71 |
| 61 if (_pending == 0 && _closed) _completer.complete(_values); | 72 if (_pending != 0) return; |
| 73 _onIdleController.add(null); | |
| 74 | |
| 75 if (!_closed) return; | |
| 76 _onIdleController.close(); | |
| 77 _completer.complete(_values); | |
| 62 }).catchError((error, stackTrace) { | 78 }).catchError((error, stackTrace) { |
| 63 if (_completer.isCompleted) return; | 79 if (_completer.isCompleted) return; |
| 64 _completer.completeError(error, stackTrace); | 80 _completer.completeError(error, stackTrace); |
| 65 }); | 81 }); |
| 66 } | 82 } |
| 67 | 83 |
| 68 /// Signals to the group that the caller is done adding futures, and so | 84 /// Signals to the group that the caller is done adding futures, and so |
| 69 /// [future] should fire once all added futures have completed. | 85 /// [future] should fire once all added futures have completed. |
| 70 void close() { | 86 void close() { |
| 71 _closed = true; | 87 _closed = true; |
| 72 if (_pending != 0) return; | 88 if (_pending != 0) return; |
| 73 if (_completer.isCompleted) return; | 89 if (_completer.isCompleted) return; |
| 74 _completer.complete(_values); | 90 _completer.complete(_values); |
| 75 } | 91 } |
| 76 } | 92 } |
| 77 | 93 |
| OLD | NEW |