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 22 : StreamChannel<T> get local => _local; 36 : late final 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 22 : StreamChannel<T> get foreign => _foreign; 43 : late final 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 [StreamSink.done] future. 54 : /// This guarantees that the local stream will never emit errors. 55 11 : StreamChannelController({bool allowForeignErrors = true, bool sync = false}) { 56 11 : var localToForeignController = StreamController<T>(sync: sync); 57 11 : var foreignToLocalController = StreamController<T>(sync: sync); 58 22 : _local = StreamChannel<T>.withGuarantees( 59 22 : foreignToLocalController.stream, localToForeignController.sink); 60 22 : _foreign = StreamChannel<T>.withGuarantees( 61 22 : localToForeignController.stream, foreignToLocalController.sink, 62 : allowSinkErrors: allowForeignErrors); 63 : } 64 : }