EsStreamController
Description
A controller with the stream it controls.
This controller allows sending data, error and done events on its #stream. This class can be used to create a simple stream that others can listen on, and to push events to that stream.
It's possible to check whether the stream is paused or not, and whether it has subscribers or not, as well as getting a callback when either of these change.
Class Methods
broadcast
  A default async controller where #stream can be listened to more than once.

     For async, the event will always be fired at a later time,
     after the code adding the event has completed.
     In that case, no guarantees are given with regard to when
     multiple listeners get the events, except that each listener will get
     all events in the correct order. Each subscription handles the events
     individually.
     If two events are sent on an async controller with two listeners,
     one of the listeners may get both events before the other listener gets any.
     A listener must be subscribed both when the event is initiated
     (that is, when #add: is called) and when the event is later delivered,
     in order to receive the event.

     Answers:
        <EsStreamController>
broadcast:onCancel:sync:
  A controller where [stream] can be listened to more than once.

     The <EsStream> answered by #stream is a broadcast stream.
     It can be listened to more than once.

     A Stream should be inert until a subscriber starts listening on it (using
     the @onListen handler to start producing events). Streams should not
     leak resources (like websockets) when no user ever listens on the stream.

     Broadcast streams do not buffer events when there is no listener.

     The controller distributes any events to all currently subscribed
     listeners at the time when #add:, #addError: or #close is called.
     It is not allowed to call #add:, #addError:, or #close before a previous
     call has answered. The controller does not have any internal queue of
     events, and if there are no listeners at the time the event is added,
     it will just be dropped, or, if it is an error, be reported as uncaught.

     Each listener subscription is handled independently,
     and if one pauses, only the pausing listener is affected.
     A paused listener will buffer events internally until unpaused or canceled.

     If @sync is true, events may be fired directly by the stream's
     subscriptions during an #add:, #addError: or #close call.
     The answered stream controller is a <EsSyncStreamController>,
     and must be used with the care and attention necessary to not break
     the <EsStream> contract.
     See [EsPromise sync] for some explanations on when a synchronous
     dispatching can be used.
     If in doubt, keep the controller non-sync.

     If @sync is false, the event will always be fired at a later time,
     after the code adding the event has completed.
     In that case, no guarantees are given with regard to when
     multiple listeners get the events, except that each listener will get
     all events in the correct order. Each subscription handles the events
     individually.
     If two events are sent on an async controller with two listeners,
     one of the listeners may get both events before the other listener gets any.
     A listener must be subscribed both when the event is initiated
     (that is, when #add: is called) and when the event is later delivered,
     in order to receive the event.

     The @onListen block is evaluated when the first listener is subscribed,
     and the @onCancel block is evaluated when there are no longer any active listeners.
     If a listener is added again later, after an @onCancel was evaluated,
     the @onListen will be evalutated again.

     Arguments:
        onListen - <Block> 0-arg block or nil.
        onCancel - <Block> 0-arg block or nil.
        sync - <Boolean> or nil. defaults to `false`
     Answers:
        <EsStreamController>
broadcastAsync
  An async controller where #stream can be listened to more than once.

     For async, the event will always be fired at a later time,
     after the code adding the event has completed.
     In that case, no guarantees are given with regard to when
     multiple listeners get the events, except that each listener will get
     all events in the correct order. Each subscription handles the events
     individually.
     If two events are sent on an async controller with two listeners,
     one of the listeners may get both events before the other listener gets any.
     A listener must be subscribed both when the event is initiated
     (that is, when #add: is called) and when the event is later delivered,
     in order to receive the event.

     Answers:
        <EsStreamController>
broadcastSync
  An async controller where #stream can be listened to more than once.

     For sync, events may be fired directly by the stream's
     subscriptions during an #add:, #addError: or #close call.
     The answered stream controller is a <EsSyncStreamController>,
     and must be used with the care and attention necessary to not break
     the <EsStream> contract.
     See [EsPromise sync] for some explanations on when a synchronous
     dispatching can be used.
     If in doubt, keep the controller non-sync.

     Answers:
        <EsStreamController>
new
  A default asynchronous controller with a #stream that supports only one single subscriber.

     Using an asynchronous controller will never give the wrong
     behavior, but using a synchronous controller incorrectly can cause
     otherwise correct programs to break.

     Answers:
        <EsStreamController>
onListen:onPause:onResume:onCancel:sync:
  A controller with a #stream that supports only one single subscriber.

     If @sync is true, the answered stream controller is a
     <EsSyncStreamController>, and must be used with the care
     and attention necessary to not break the <EsStream> contract. If in doubt,
     use the non-sync version.

     Using an asynchronous controller will never give the wrong
     behavior, but using a synchronous controller incorrectly can cause
     otherwise correct programs to break.

     A synchronous controller is only intended for optimizing event
     propagation when one asynchronous event immediately triggers another.
     It should not be used unless the calls to #add: or #addError:
     are guaranteed to occur in places where it won't break `EsStream` invariants.

     Use synchronous controllers only to forward (potentially transformed)
     events from another stream or a future.

     A Stream should be inert until a subscriber starts listening on it (using
     the @onListen handler to start producing events). Streams should not
     leak resources (like websockets) when no user ever listens on the stream.

     The controller buffers all incoming events until a subscriber is
     registered, but this feature should only be used in rare circumstances.

     The @onPause block is called when the stream becomes
     paused. @onResume is called when the stream resumed.

     The @onListen handler is called when the stream
     receives its listener and [onCancel] when the listener ends
     its subscription. If @onCancel needs to perform an asynchronous operation,
     @onCancel should return a future that completes when the cancel operation
     is done.

     If the stream is canceled before the controller needs data the
    @onResume call might not be executed.

     Arguments:
        onListen - <Block> 0-arg block or nil.
        onPause - <Block> 0-arg block or nil.
        onResume - <Block> 0-arg block or nil.
        onCancel - <Block> 0-arg block or nil. Answers an <EsFuture> or nil.
        sync - <Boolean> or nil. defaults to `false`
     Answers:
        <EsStreamController>
single
  A default asynchronous controller with a #stream that supports only one single subscriber.

     Using an asynchronous controller will never give the wrong
     behavior, but using a synchronous controller incorrectly can cause
     otherwise correct programs to break.

     Answers:
        <EsStreamController>
singleAsync
  A asynchronous controller with a #stream that supports only one single subscriber.

     Using an asynchronous controller will never give the wrong
     behavior, but using a synchronous controller incorrectly can cause
     otherwise correct programs to break.

     Answers:
        <EsStreamController>
singleSync
  A synchronous controller with a #stream that supports only one single subscriber.

     The answered stream controller is a
     <EsSyncStreamController>, and must be used with the care
     and attention necessary to not break the <EsStream> contract. If in doubt,
     use the non-sync version.

     A synchronous controller is only intended for optimizing event
     propagation when one asynchronous event immediately triggers another.
     It should not be used unless the calls to #add: or #addError:
     are guaranteed to occur in places where it won't break `EsStream` invariants.

     Use synchronous controllers only to forward (potentially transformed)
     events from another stream or a future.

     Answers:
        <EsStreamController>
Instance Methods
add:
  Sends a data @event.

     Listeners receive this event in a later scheduled task process.

     Note that a synchronous controller (created by passing true to the `sync`
     argument of the `EsStreamController` creational method) delivers events
     immediately. Since this behavior violates the contract mentioned here,
     synchronous controllers should only be used as described in the
     documentation to ensure that the delivered events always *appear* as if
     they were delivered in a separate scheduled task process

     Arguments:
        event - <Object>
     Answers:
        <EsStreamController> self
addError:stackTrace:
  Sends or enqueues an error event.

     Listeners receive this event at a later scheduled task process. This behavior can be
     overridden by using `sync` controllers. Note, however, that sync
     controllers have to satisfy the preconditions mentioned in the
     documentation of the creational apis

     Arguments:
        error - <Object>
        stackTrace - <EsAsyncStackTrace>
     Answers:
        <EsStreamController> self
addStream:
  Receives events from @source and puts them into this controller's stream.
     Answers a future which completes when the source stream is done.

     See #addStream:cancelOnError: for more details
addStream:cancelOnError:
  Receives events from @source and puts them into this controller's stream.

     Returns a future which completes when the source stream is done.

     Events must not be added directly to this controller using #add:,
     #addError:, #close or #addStream:, until the answered future
     is complete.

     Data and error events are forwarded to this controller's stream. A done
     event on the source will end the `addStream:` operation and complete the
     answered future.

     If @cancelOnError is `true`, only the first error on @source is
     forwarded to the controller's stream, and the `addStream:` ends
     after this. If @cancelOnError is false, all errors are forwarded
     and only a done event will end the `addStream:`.
     If @cancelOnError is omitted or `nil`, it defaults to `false`.

     Arguments:
        source - <EsStream>
        cancelOnError - <Boolean>
     Answers:   
        <EsFuture>
close
  Closes the stream.

     No further events can be added to a closed stream.

     The answered future is the same future provided by #done.
     It is completed when the stream listeners is done sending events,
     This happens either when the done event has been sent,
     or when the subscriber on a single-subscription stream is canceled.

     A broadcast stream controller will send the done event
     even if listeners are paused, so some broadcast events may not have been
     received yet when the answered future completes.

     If none listens to a non-broadcast stream, or the listener pauses and never resumes,
     the done event will not be sent and this future will never complete.

     Answers:   
        <EsFuture>
done
  A future which is completed when the stream controller is done
     sending events.

     This happens either when the done event has been sent, or if the
     subscriber on a single-subscription stream is canceled.

     A broadcast stream controller will send the done event
     even if listeners are paused, so some broadcast events may not have been
     received yet when the answered future completes.

     If there is no listener on a non-broadcast stream,
     or the listener pauses and never resumes,
     the done event will not be sent and this future will never complete.

     Answers:
        <EsFuture>
hasListener
  Whether there is a subscriber on the <EsStream>

     Answers:
        <Boolean>
isClosed
  Whether the stream controller is closed for adding more events.

     The controller becomes closed by calling the #close method.
     New events cannot be added, by calling #add: or #addError:*,
     to a closed controller.

     If the controller is closed,
     the `done` event might not have been delivered yet,
     but it has been scheduled, and it is too late to add more events.

     Answers:
        <Boolean>
isPaused
  Whether the stream controller would need to buffer events.

     This is the case if the controller's stream has a listener and it is
     paused, or if it has not received a listener yet. In that case, the
     controller is considered paused as well.

     A broadcast stream controller is never considered paused. It always
     forwards its events to all uncanceled subscriptions, if any,
     and let the subscriptions handle their own pausing and buffering.

     Answers:
        <Boolean>
onCancel
  The 0-arg block which is evaluated when the stream is canceled..
     May be set to `nil`, in which case no block eval will happen.

     Answers:
        <Block> 0-arg block or nil. Answers <EsFuture>
onListen
  The 0-arg block which is evaluated when the stream is listened to.
     May be set to `nil`, in which case no handler will happen.

     Answers:
        <Block> 0-arg block or nil
onPause
  The 0-arg block which is evaluated when the stream is paused..
     May be set to `nil`, in which case no block eval will happen.
     Pause related blocks are not supported on broadcast stream controllers.

     Answers:
        <Block> 0-arg block or nil
onResume
  The 0-arg block which is evaluated when the stream is resumed..
     May be set to `nil`, in which case no block eval will happen.
     Pause/resume related blocks are not supported on broadcast stream controllers.

     Answers:
        <Block> 0-arg block or nil
sink
  Answers a view of this object that only exposes the <EsStreamSink> interface.

     Answers:
        <EsStreamSink>
stream
  The stream that this controller is controlling.

     Answers:
        <EsStream>
Last modified date: 04/21/2022