LCOV - code coverage report
Current view: top level - async-2.5.0/lib/src - future_group.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 0 27 0.0 %
Date: 2021-11-28 14:37:50 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           0 :   Future<List<T>> get future => _completer.future;
      34             :   final _completer = 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           0 :   Stream get onIdle =>
      45           0 :       (_onIdleController ??= StreamController.broadcast(sync: true)).stream;
      46             : 
      47             :   StreamController? _onIdleController;
      48             : 
      49             :   /// The values emitted by the futures that have been added to the group, in
      50             :   /// the order they were added.
      51             :   ///
      52             :   /// The slots for futures that haven't completed yet are `null`.
      53             :   final _values = <T?>[];
      54             : 
      55             :   /// Wait for [task] to complete.
      56           0 :   @override
      57             :   void add(Future<T> task) {
      58           0 :     if (_closed) throw StateError('The FutureGroup is closed.');
      59             : 
      60             :     // Ensure that future values are put into [values] in the same order they're
      61             :     // added to the group by pre-allocating a slot for them and recording its
      62             :     // index.
      63           0 :     var index = _values.length;
      64           0 :     _values.add(null);
      65             : 
      66           0 :     _pending++;
      67           0 :     task.then((value) {
      68           0 :       if (_completer.isCompleted) return null;
      69             : 
      70           0 :       _pending--;
      71           0 :       _values[index] = value;
      72             : 
      73           0 :       if (_pending != 0) return null;
      74           0 :       var onIdleController = _onIdleController;
      75           0 :       if (onIdleController != null) onIdleController.add(null);
      76             : 
      77           0 :       if (!_closed) return null;
      78           0 :       if (onIdleController != null) onIdleController.close();
      79           0 :       _completer.complete(_values.whereType<T>().toList());
      80           0 :     }).catchError((Object error, StackTrace stackTrace) {
      81           0 :       if (_completer.isCompleted) return null;
      82           0 :       _completer.completeError(error, stackTrace);
      83             :     });
      84             :   }
      85             : 
      86             :   /// Signals to the group that the caller is done adding futures, and so
      87             :   /// [future] should fire once all added futures have completed.
      88           0 :   @override
      89             :   void close() {
      90           0 :     _closed = true;
      91           0 :     if (_pending != 0) return;
      92           0 :     if (_completer.isCompleted) return;
      93           0 :     _completer.complete(_values.whereType<T>().toList());
      94             :   }
      95             : }

Generated by: LCOV version 1.14