Line data Source code
1 : // Copyright (c) 2016, 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 '../stream_channel.dart';
8 :
9 : /// A controller for exposing a new [StreamChannel].
10 : ///
11 : /// This exposes two connected [StreamChannel]s, [local] and [foreign]. The
12 : /// user's code should use [local] to emit and receive events. Then [foreign]
13 : /// can be returned for others to use. For example, here's a simplified version
14 : /// of the implementation of [new IsolateChannel]:
15 : ///
16 : /// ```dart
17 : /// StreamChannel isolateChannel(ReceivePort receivePort, SendPort sendPort) {
18 : /// var controller = new StreamChannelController(allowForeignErrors: false);
19 : ///
20 : /// // Pipe all events from the receive port into the local sink...
21 : /// receivePort.pipe(controller.local.sink);
22 : ///
23 : /// // ...and all events from the local stream into the send port.
24 : /// controller.local.stream.listen(sendPort.send, onDone: receivePort.close);
25 : ///
26 : /// // Then return the foreign controller for your users to use.
27 : /// return controller.foreign;
28 : /// }
29 : /// ```
30 : class StreamChannelController<T> {
31 : /// The local channel.
32 : ///
33 : /// This channel should be used directly by the creator of this
34 : /// [StreamChannelController] to send and receive events.
35 0 : StreamChannel<T> get local => _local;
36 : StreamChannel<T> _local;
37 :
38 : /// The foreign channel.
39 : ///
40 : /// This channel should be returned to external users so they can communicate
41 : /// with [local].
42 0 : StreamChannel<T> get foreign => _foreign;
43 : StreamChannel<T> _foreign;
44 :
45 : /// Creates a [StreamChannelController].
46 : ///
47 : /// If [sync] is true, events added to either channel's sink are synchronously
48 : /// dispatched to the other channel's stream. This should only be done if the
49 : /// source of those events is already asynchronous.
50 : ///
51 : /// If [allowForeignErrors] is `false`, errors are not allowed to be passed to
52 : /// the foreign channel's sink. If any are, the connection will close and the
53 : /// error will be forwarded to the foreign channel's [Sink.done] future. This
54 : /// guarantees that the local stream will never emit errors.
55 0 : StreamChannelController({bool allowForeignErrors: true, bool sync: false}) {
56 0 : var localToForeignController = new StreamController<T>(sync: sync);
57 0 : var foreignToLocalController = new StreamController<T>(sync: sync);
58 0 : _local = new StreamChannel<T>.withGuarantees(
59 0 : foreignToLocalController.stream, localToForeignController.sink);
60 0 : _foreign = new StreamChannel<T>.withGuarantees(
61 0 : localToForeignController.stream, foreignToLocalController.sink,
62 : allowSinkErrors: allowForeignErrors);
63 : }
64 : }
|