Index: lib/stream_channel.dart |
diff --git a/lib/stream_channel.dart b/lib/stream_channel.dart |
index c4e28a0e37329ae229f21569b07a901dcc04fbef..5d666acca93aa164794aeffc3c25b244d4d06b60 100644 |
--- a/lib/stream_channel.dart |
+++ b/lib/stream_channel.dart |
@@ -8,18 +8,55 @@ export 'src/multi_channel.dart'; |
/// An abstract class representing a two-way communication channel. |
/// |
-/// Subclasses are strongly encouraged to mix in or extend [StreamChannelMixin] |
-/// to get default implementations of the various instance methods. Adding new |
-/// methods to this interface will not be considered a breaking change if |
-/// implementations are also added to [StreamChannelMixin]. |
+/// Users should consider the [stream] emitting a "done" event to be the |
+/// canonical indicator that the channel has closed. If they wish to close the |
+/// channel, they should close the [sink]—canceling their stream subscription is |
+/// not sufficient. Protocol errors may be emitted through the stream or through |
+/// [Sink.done], depending on their underlying cause. Note that the sink may |
+/// silently drop events if the channel closes before the stream has a listener. |
+/// |
+/// Implementations are strongly encouraged to mix in or extend |
+/// [StreamChannelMixin] to get default implementations of the various instance |
+/// methods. Adding new methods to this interface will not be considered a |
+/// breaking change if implementations are also added to [StreamChannelMixin]. |
+/// |
+/// Implementations must provide the following guarantees: |
+/// |
+/// * The stream is single-subscription, and must follow all the guarantees of |
+/// single-subscription streams. |
+/// |
+/// * Closing the sink causes the stream to close before it emits any more |
+/// events. |
+/// |
+/// * After the stream closes, the sink is automatically closed. If this |
+/// happens, sink methods should silently drop their arguments at least until |
+/// [Sink.done] and the stream's `onDone` callback fire. |
+/// |
+/// * If the stream closes before it has a listener, the sink may either close |
+/// or silently drop events. |
+/// |
+/// * Canceling the stream's subscription has no effect on the sink. The channel |
+/// must still be able to respond to the other endpoint closing the channel |
+/// even after the subscription has been canceled. |
+/// |
+/// * The sink *either* forwards errors to the other endpoint *or* closes as |
+/// soon as an error is added and forwards that error to the [Sink.done] |
+/// future. |
+/// |
+/// These guarantees allow users to interact uniformly with all implementations, |
+/// and ensure that either endpoint closing the stream produces consistent |
+/// behavior. |
abstract class StreamChannel<T> { |
- /// The stream that emits values from the other endpoint. |
+ /// The single-subscription stream that emits values from the other endpoint. |
Stream<T> get stream; |
/// The sink for sending values to the other endpoint. |
StreamSink<T> get sink; |
/// Creates a new [StreamChannel] that communicates over [stream] and [sink]. |
+ /// |
+ /// Note that this stream/sink pair must provide the guarantees listed in the |
+ /// [StreamChannel] documentation. |
factory StreamChannel(Stream<T> stream, StreamSink<T> sink) => |
new _StreamChannel<T>(stream, sink); |