LCOV - code coverage report
Current view: top level - async-1.13.3/lib/src - future_group.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 19 25 76.0 %
Date: 2017-10-10 20:17:03 Functions: 0 0 -

          Line data    Source code
       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
       3             : // BSD-style license that can be found in the LICENSE file.
       4             : 
       5             : import 'dart:async';
       6             : 
       7             : /// A collection of futures waits until all added [Future]s complete.
       8             : ///
       9             : /// Futures are added to the group with [add]. Once you're finished adding
      10             : /// futures, signal that by calling [close]. Then, once all added futures have
      11             : /// completed, [future] will complete with a list of values from the futures in
      12             : /// the group, in the order they were added.
      13             : ///
      14             : /// If any added future completes with an error, [future] will emit that error
      15             : /// and the group will be closed, regardless of the state of other futures in
      16             : /// the group.
      17             : ///
      18             : /// This is similar to [Future.wait] with `eagerError` set to `true`, except
      19             : /// that a [FutureGroup] can have futures added gradually over time rather than
      20             : /// needing them all at once.
      21             : class FutureGroup<T> implements Sink<Future<T>> {
      22             :   /// The number of futures that have yet to complete.
      23             :   var _pending = 0;
      24             : 
      25             :   /// Whether [close] has been called.
      26             :   var _closed = false;
      27             : 
      28             :   /// The future that fires once [close] has been called and all futures in the
      29             :   /// group have completed.
      30             :   ///
      31             :   /// This will also complete with an error if any of the futures in the group
      32             :   /// fails, regardless of whether [close] was called.
      33          10 :   Future<List<T>> get future => _completer.future;
      34             :   final _completer = new Completer<List<T>>();
      35             : 
      36             :   /// Whether this group has no pending futures.
      37           0 :   bool get isIdle => _pending == 0;
      38             : 
      39             :   /// A broadcast stream that emits a `null` event whenever the last pending
      40             :   /// future in this group completes.
      41             :   ///
      42             :   /// Once this group isn't waiting on any futures *and* [close] has been
      43             :   /// called, this stream will close.
      44             :   Stream get onIdle {
      45           0 :     if (_onIdleController == null) {
      46           0 :       _onIdleController = new StreamController.broadcast(sync: true);
      47             :     }
      48           0 :     return _onIdleController.stream;
      49             :   }
      50             : 
      51             :   StreamController _onIdleController;
      52             : 
      53             :   /// The values emitted by the futures that have been added to the group, in
      54             :   /// the order they were added.
      55             :   ///
      56             :   /// The slots for futures that haven't completed yet are `null`.
      57             :   final _values = new List<T>();
      58             : 
      59             :   /// Wait for [task] to complete.
      60             :   void add(Future<T> task) {
      61           5 :     if (_closed) throw new StateError("The FutureGroup is closed.");
      62             : 
      63             :     // Ensure that future values are put into [values] in the same order they're
      64             :     // added to the group by pre-allocating a slot for them and recording its
      65             :     // index.
      66          10 :     var index = _values.length;
      67          10 :     _values.add(null);
      68             : 
      69          10 :     _pending++;
      70           5 :     task.then((value) {
      71          10 :       if (_completer.isCompleted) return null;
      72             : 
      73          10 :       _pending--;
      74          10 :       _values[index] = value;
      75             : 
      76          10 :       if (_pending != 0) return null;
      77           5 :       if (_onIdleController != null) _onIdleController.add(null);
      78             : 
      79           5 :       if (!_closed) return null;
      80           5 :       if (_onIdleController != null) _onIdleController.close();
      81          15 :       _completer.complete(_values);
      82           5 :     }).catchError((error, stackTrace) {
      83           0 :       if (_completer.isCompleted) return null;
      84           0 :       _completer.completeError(error, stackTrace);
      85             :     });
      86             :   }
      87             : 
      88             :   /// Signals to the group that the caller is done adding futures, and so
      89             :   /// [future] should fire once all added futures have completed.
      90             :   void close() {
      91           5 :     _closed = true;
      92          10 :     if (_pending != 0) return;
      93          10 :     if (_completer.isCompleted) return;
      94          15 :     _completer.complete(_values);
      95             :   }
      96             : }

Generated by: LCOV version 1.13