LCOV - code coverage report
Current view: top level - async-1.13.3/lib/src - cancelable_operation.dart (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 0 45 0.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             : import 'package:async/async.dart';
       8             : 
       9             : import 'utils.dart';
      10             : 
      11             : /// An asynchronous operation that can be cancelled.
      12             : ///
      13             : /// The value of this operation is exposed as [value]. When this operation is
      14             : /// cancelled, [value] won't complete either successfully or with an error. If
      15             : /// [value] has already completed, cancelling the operation does nothing.
      16             : class CancelableOperation<T> {
      17             :   /// The completer that produced this operation.
      18             :   ///
      19             :   /// This is canceled when [cancel] is called.
      20             :   final CancelableCompleter<T> _completer;
      21             : 
      22           0 :   CancelableOperation._(this._completer);
      23             : 
      24             :   /// Creates a [CancelableOperation] wrapping [inner].
      25             :   ///
      26             :   /// When this operation is canceled, [onCancel] will be called and any value
      27             :   /// or error produced by [inner] will be discarded. If [onCancel] returns a
      28             :   /// [Future], it will be forwarded to [cancel].
      29             :   ///
      30             :   /// [onCancel] will be called synchronously when the operation is canceled.
      31             :   /// It's guaranteed to only be called once.
      32             :   factory CancelableOperation.fromFuture(Future<T> inner,
      33             :       {FutureOr onCancel()}) {
      34           0 :     var completer = new CancelableCompleter<T>(onCancel: onCancel);
      35           0 :     completer.complete(inner);
      36           0 :     return completer.operation;
      37             :   }
      38             : 
      39             :   /// The value returned by the operation.
      40           0 :   Future<T> get value => _completer._inner.future;
      41             : 
      42             :   /// Creates a [Stream] containing the result of this operation.
      43             :   ///
      44             :   /// This is like `value.asStream()`, but if a subscription to the stream is
      45             :   /// canceled, this is as well.
      46             :   Stream<T> asStream() {
      47             :     var controller =
      48           0 :         new StreamController<T>(sync: true, onCancel: _completer._cancel);
      49             : 
      50           0 :     value.then((value) {
      51           0 :       controller.add(value);
      52           0 :       controller.close();
      53             :     }, onError: (error, stackTrace) {
      54           0 :       controller.addError(error, stackTrace);
      55           0 :       controller.close();
      56             :     });
      57           0 :     return controller.stream;
      58             :   }
      59             : 
      60             :   /// Creates a [Future] that completes when this operation completes *or* when
      61             :   /// it's cancelled.
      62             :   ///
      63             :   /// If this operation completes, this completes to the same result as [value].
      64             :   /// If this operation is cancelled, the returned future waits for the future
      65             :   /// returned by [cancel], then completes to [cancellationValue].
      66             :   Future valueOrCancellation([T cancellationValue]) {
      67           0 :     var completer = new Completer<T>.sync();
      68           0 :     value.then((result) => completer.complete(result),
      69           0 :         onError: completer.completeError);
      70             : 
      71           0 :     _completer._cancelMemo.future.then((_) {
      72           0 :       completer.complete(cancellationValue);
      73           0 :     }, onError: completer.completeError);
      74             : 
      75           0 :     return completer.future;
      76             :   }
      77             : 
      78             :   /// Cancels this operation.
      79             :   ///
      80             :   /// This returns the [Future] returned by the [CancelableCompleter]'s
      81             :   /// `onCancel` callback. Unlike [Stream.cancel], it never returns `null`.
      82           0 :   Future cancel() => _completer._cancel();
      83             : }
      84             : 
      85             : /// A completer for a [CancelableOperation].
      86             : class CancelableCompleter<T> {
      87             :   /// The completer for the wrapped future.
      88             :   final Completer<T> _inner;
      89             : 
      90             :   /// The callback to call if the future is canceled.
      91             :   final FutureOrCallback _onCancel;
      92             : 
      93             :   /// Creates a new completer for a [CancelableOperation].
      94             :   ///
      95             :   /// When the future operation canceled, as long as the completer hasn't yet
      96             :   /// completed, [onCancel] is called. If [onCancel] returns a [Future], it's
      97             :   /// forwarded to [CancelableOperation.cancel].
      98             :   ///
      99             :   /// [onCancel] will be called synchronously when the operation is canceled.
     100             :   /// It's guaranteed to only be called once.
     101             :   CancelableCompleter({FutureOr onCancel()})
     102             :       : _onCancel = onCancel,
     103           0 :         _inner = new Completer<T>() {
     104           0 :     _operation = new CancelableOperation<T>._(this);
     105             :   }
     106             : 
     107             :   /// The operation controlled by this completer.
     108           0 :   CancelableOperation<T> get operation => _operation;
     109             :   CancelableOperation<T> _operation;
     110             : 
     111             :   /// Whether the completer has completed.
     112           0 :   bool get isCompleted => _isCompleted;
     113             :   bool _isCompleted = false;
     114             : 
     115             :   /// Whether the completer was canceled before being completed.
     116           0 :   bool get isCanceled => _isCanceled;
     117             :   bool _isCanceled = false;
     118             : 
     119             :   /// The memoizer for [_cancel].
     120             :   final _cancelMemo = new AsyncMemoizer();
     121             : 
     122             :   /// Completes [operation] to [value].
     123             :   ///
     124             :   /// If [value] is a [Future], this will complete to the result of that
     125             :   /// [Future] once it completes.
     126             :   void complete([value]) {
     127           0 :     if (_isCompleted) throw new StateError("Operation already completed");
     128           0 :     _isCompleted = true;
     129             : 
     130           0 :     if (value is! Future) {
     131           0 :       if (_isCanceled) return;
     132           0 :       _inner.complete(value);
     133             :       return;
     134             :     }
     135             : 
     136           0 :     if (_isCanceled) {
     137             :       // Make sure errors from [value] aren't top-leveled.
     138           0 :       value.catchError((_) {});
     139             :       return;
     140             :     }
     141             : 
     142           0 :     value.then((result) {
     143           0 :       if (_isCanceled) return;
     144           0 :       _inner.complete(result);
     145             :     }, onError: (error, stackTrace) {
     146           0 :       if (_isCanceled) return;
     147           0 :       _inner.completeError(error, stackTrace);
     148             :     });
     149             :   }
     150             : 
     151             :   /// Completes [operation] to [error].
     152             :   void completeError(Object error, [StackTrace stackTrace]) {
     153           0 :     if (_isCompleted) throw new StateError("Operation already completed");
     154           0 :     _isCompleted = true;
     155             : 
     156           0 :     if (_isCanceled) return;
     157           0 :     _inner.completeError(error, stackTrace);
     158             :   }
     159             : 
     160             :   /// Cancel the completer.
     161             :   Future _cancel() {
     162           0 :     if (_inner.isCompleted) return new Future.value();
     163             : 
     164           0 :     return _cancelMemo.runOnce(() {
     165           0 :       _isCanceled = true;
     166           0 :       if (_onCancel != null) return _onCancel();
     167             :     });
     168             :   }
     169             : }

Generated by: LCOV version 1.13