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

Unified Diff: utils/pub/error_group.dart

Issue 14297021: Move pub into sdk/lib/_internal. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Disallow package: imports of pub. Created 7 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « utils/pub/entrypoint.dart ('k') | utils/pub/exit_codes.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: utils/pub/error_group.dart
diff --git a/utils/pub/error_group.dart b/utils/pub/error_group.dart
deleted file mode 100644
index 694638c24716b935065b71c6fcbbcad3bd8bb9bf..0000000000000000000000000000000000000000
--- a/utils/pub/error_group.dart
+++ /dev/null
@@ -1,277 +0,0 @@
-// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library error_group;
-
-import 'dart:async';
-
-import 'utils.dart';
-
-/// An [ErrorGroup] entangles the errors of multiple [Future]s and [Stream]s
-/// with one another. This allows APIs to expose multiple [Future]s and
-/// [Stream]s that have identical error conditions without forcing API consumers
-/// to attach error handling to objects they don't care about.
-///
-/// To use an [ErrorGroup], register [Future]s and [Stream]s with it using
-/// [registerFuture] and [registerStream]. These methods return wrapped versions
-/// of the [Future]s and [Stream]s, which should then be used in place of the
-/// originals. For example:
-///
-/// var errorGroup = new ErrorGroup();
-/// future = errorGroup.registerFuture(future);
-/// stream = errorGroup.registerStream(stream);
-///
-/// An [ErrorGroup] has two major effects on its wrapped members:
-///
-/// * An error in any member of the group will be propagated to every member
-/// that hasn't already completed. If those members later complete, their
-/// values will be ignored.
-/// * If any member of this group has a listener, errors on members without
-/// listeners won't get passed to the top-level error handler.
-class ErrorGroup {
- /// The [Future]s that are members of [this].
- final _futures = <_ErrorGroupFuture>[];
-
- /// The [Stream]s that are members of [this].
- final _streams = <_ErrorGroupStream>[];
-
- /// Whether [this] has completed, either successfully or with an error.
- var _isDone = false;
-
- /// The [Completer] for [done].
- final _doneCompleter = new Completer();
-
- /// The underlying [Future] for [done]. We need to be able to access it
- /// internally as an [_ErrorGroupFuture] so we can check if it has listeners
- /// and signal errors on it.
- _ErrorGroupFuture _done;
-
- /// Returns a [Future] that completes successully when all members of [this]
- /// are complete, or with an error if any member receives an error.
- ///
- /// This [Future] is effectively in the group in that an error on it won't be
- /// passed to the top-level error handler unless no members of the group have
- /// listeners attached.
- Future get done => _done;
-
- /// Creates a new group with no members.
- ErrorGroup() {
- this._done = new _ErrorGroupFuture(this, _doneCompleter.future);
- }
-
- /// Registers a [Future] as a member of [this]. Returns a wrapped version of
- /// [future] that should be used in its place.
- ///
- /// If all members of [this] have already completed successfully or with an
- /// error, it's a [StateError] to try to register a new [Future].
- Future registerFuture(Future future) {
- if (_isDone) {
- throw new StateError("Can't register new members on a complete "
- "ErrorGroup.");
- }
-
- var wrapped = new _ErrorGroupFuture(this, future);
- _futures.add(wrapped);
- return wrapped;
- }
-
- /// Registers a [Stream] as a member of [this]. Returns a wrapped version of
- /// [stream] that should be used in its place. The returned [Stream] will be
- /// multi-subscription if and only if [stream] is.
- ///
- /// Since all errors in a group are passed to all members, the returned
- /// [Stream] will automatically unsubscribe all its listeners when it
- /// encounters an error.
- ///
- /// If all members of [this] have already completed successfully or with an
- /// error, it's a [StateError] to try to register a new [Stream].
- Stream registerStream(Stream stream) {
- if (_isDone) {
- throw new StateError("Can't register new members on a complete "
- "ErrorGroup.");
- }
-
- var wrapped = new _ErrorGroupStream(this, stream);
- _streams.add(wrapped);
- return wrapped;
- }
-
- /// Sends [error] to all members of [this]. Like errors that come from
- /// members, this will only be passed to the top-level error handler if no
- /// members have listeners.
- ///
- /// If all members of [this] have already completed successfully or with an
- /// error, it's a [StateError] to try to signal an error.
- void signalError(var error) {
- if (_isDone) {
- throw new StateError("Can't signal errors on a complete ErrorGroup.");
- }
-
- _signalError(error);
- }
-
- /// Signal an error internally. This is just like [signalError], but instead
- /// of throwing an error if [this] is complete, it just does nothing.
- void _signalError(var error) {
- if (_isDone) return;
-
- var caught = false;
- for (var future in _futures) {
- if (future._isDone || future._hasListeners) caught = true;
- future._signalError(error);
- }
-
- for (var stream in _streams) {
- if (stream._isDone || stream._hasListeners) caught = true;
- stream._signalError(error);
- }
-
- _isDone = true;
- _done._signalError(error);
- if (!caught && !_done._hasListeners) error.throwDelayed();
- }
-
- /// Notifies [this] that one of its member [Future]s is complete.
- void _signalFutureComplete(_ErrorGroupFuture future) {
- if (_isDone) return;
-
- _isDone = _futures.every((future) => future._isDone) &&
- _streams.every((stream) => stream._isDone);
- if (_isDone) _doneCompleter.complete();
- }
-
- /// Notifies [this] that one of its member [Stream]s is complete.
- void _signalStreamComplete(_ErrorGroupStream stream) {
- if (_isDone) return;
-
- _isDone = _futures.every((future) => future._isDone) &&
- _streams.every((stream) => stream._isDone);
- if (_isDone) _doneCompleter.complete();
- }
-}
-
-/// A [Future] wrapper that keeps track of whether it's been completed and
-/// whether it has any listeners. It also notifies its parent [ErrorGroup] when
-/// it completes successfully or receives an error.
-class _ErrorGroupFuture implements Future {
- /// The parent [ErrorGroup].
- final ErrorGroup _group;
-
- /// Whether [this] has completed, either successfully or with an error.
- var _isDone = false;
-
- /// The underlying [Completer] for [this].
- final _completer = new Completer();
-
- /// Whether [this] has any listeners.
- bool _hasListeners = false;
-
- /// Creates a new [_ErrorGroupFuture] that's a child of [_group] and wraps
- /// [inner].
- _ErrorGroupFuture(this._group, Future inner) {
- inner.then((value) {
- if (!_isDone) _completer.complete(value);
- _isDone = true;
- _group._signalFutureComplete(this);
- }).catchError((error) => _group._signalError(error));
-
- // Make sure _completer.future doesn't automatically send errors to the
- // top-level.
- _completer.future.catchError((_) {});
- }
-
- Future then(onValue(value), {onError(error)}) {
- _hasListeners = true;
- return _completer.future.then(onValue, onError: onError);
- }
-
- Future catchError(onError(error), {bool test(Object error)}) {
- _hasListeners = true;
- return _completer.future.catchError(onError, test: test);
- }
-
- Future whenComplete(void action()) {
- _hasListeners = true;
- return _completer.future.whenComplete(action);
- }
-
- Stream asStream() {
- _hasListeners = true;
- return _completer.future.asStream();
- }
-
- /// Signal that an error from [_group] should be propagated through [this],
- /// unless it's already complete.
- void _signalError(var error) {
- if (!_isDone) _completer.completeError(error);
- _isDone = true;
- }
-}
-
-// TODO(nweiz): currently streams never top-level unhandled errors (issue 7843).
-// When this is fixed, this class will need to prevent such errors from being
-// top-leveled.
-/// A [Stream] wrapper that keeps track of whether it's been completed and
-/// whether it has any listeners. It also notifies its parent [ErrorGroup] when
-/// it completes successfully or receives an error.
-class _ErrorGroupStream extends Stream {
- /// The parent [ErrorGroup].
- final ErrorGroup _group;
-
- /// Whether [this] has completed, either successfully or with an error.
- var _isDone = false;
-
- /// The underlying [StreamController] for [this].
- final StreamController _controller;
-
- /// The controller's [Stream]. May be different than `_controller.stream` if
- /// the wrapped stream is a broadcasting stream.
- Stream _stream;
-
- /// The [StreamSubscription] that connects the wrapped [Stream] to
- /// [_controller].
- StreamSubscription _subscription;
-
- /// Whether [this] has any listeners.
- bool get _hasListeners => _controller.hasListener;
-
- /// Creates a new [_ErrorGroupFuture] that's a child of [_group] and wraps
- /// [inner].
- _ErrorGroupStream(this._group, Stream inner)
- : _controller = new StreamController() {
- this._stream = inner.isBroadcast
- ? _controller.stream.asBroadcastStream()
- : _controller.stream;
- _subscription = inner.listen((v) {
- _controller.add(v);
- }, onError: (e) {
- _group._signalError(e);
- }, onDone: () {
- _isDone = true;
- _group._signalStreamComplete(this);
- _controller.close();
- });
- }
-
- StreamSubscription listen(void onData(value),
- {void onError(var error), void onDone(),
- bool cancelOnError}) {
- return _stream.listen(onData,
- onError: onError,
- onDone: onDone,
- cancelOnError: true);
- }
-
- /// Signal that an error from [_group] should be propagated through [this],
- /// unless it's already complete.
- void _signalError(var e) {
- if (_isDone) return;
- _subscription.cancel();
- // Call these asynchronously to work around issue 7913.
- new Future.value().then((_) {
- _controller.addError(e);
- _controller.close();
- });
- }
-}
« no previous file with comments | « utils/pub/entrypoint.dart ('k') | utils/pub/exit_codes.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698