blob: 45b2865ed3a495a74e50ae6c04963d1d599df87f [file] [log] [blame]
// Copyright (c) 2016, 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.
import 'dart:async';
import '../stream_channel.dart';
/// A controller for exposing a new [StreamChannel].
///
/// This exposes two connected [StreamChannel]s, [local] and [foreign]. The
/// user's code should use [local] to emit and receive events. Then [foreign]
/// can be returned for others to use. For example, here's a simplified version
/// of the implementation of [new IsolateChannel]:
///
/// ```dart
/// StreamChannel isolateChannel(ReceivePort receivePort, SendPort sendPort) {
/// var controller = new StreamChannelController(allowForeignErrors: false);
///
/// // Pipe all events from the receive port into the local sink...
/// receivePort.pipe(controller.local.sink);
///
/// // ...and all events from the local stream into the send port.
/// controller.local.stream.listen(sendPort.send, onDone: receivePort.close);
///
/// // Then return the foreign controller for your users to use.
/// return controller.foreign;
/// }
/// ```
class StreamChannelController<T> {
/// The local channel.
///
/// This channel should be used directly by the creator of this
/// [StreamChannelController] to send and receive events.
StreamChannel<T> get local => _local;
StreamChannel<T> _local;
/// The foreign channel.
///
/// This channel should be returned to external users so they can communicate
/// with [local].
StreamChannel<T> get foreign => _foreign;
StreamChannel<T> _foreign;
/// Creates a [StreamChannelController].
///
/// If [sync] is true, events added to either channel's sink are synchronously
/// dispatched to the other channel's stream. This should only be done if the
/// source of those events is already asynchronous.
///
/// If [allowForeignErrors] is `false`, errors are not allowed to be passed to
/// the foreign channel's sink. If any are, the connection will close and the
/// error will be forwarded to the foreign channel's [Sink.done] future. This
/// guarantees that the local stream will never emit errors.
StreamChannelController({bool allowForeignErrors: true, bool sync: false}) {
var localToForeignController = new StreamController<T>(sync: sync);
var foreignToLocalController = new StreamController<T>(sync: sync);
_local = new StreamChannel<T>.withGuarantees(
foreignToLocalController.stream, localToForeignController.sink);
_foreign = new StreamChannel<T>.withGuarantees(
localToForeignController.stream, foreignToLocalController.sink,
allowSinkErrors: allowForeignErrors);
}
}