# SynchronousStreamController<T> class

A stream controller that delivers its events synchronously.

A synchronous stream controller is intended for cases where an already asynchronous event triggers an event on a stream.

Instead of adding the event to the stream in a later microtask, causing extra latency, the event is instead fired immediately by the synchronous stream controller, as if the stream event was the current event or microtask.

The synchronous stream controller can be used to break the contract on Stream, and it must be used carefully to avoid doing so.

The only advantage to using a SynchronousStreamController over a normal StreamController is the improved latency. Only use the synchronous version if the improvement is significant, and if its use is safe. Otherwise just use a normal stream controller, which will always have the correct behavior for a Stream, and won't accidentally break other code.

Adding events to a synchronous controller should only happen as the very last part of the handling of the original event. At that point, adding an event to the stream is equivalent to returning to the event loop and adding the event in the next microtask.

Each listener callback will be run as if it was a top-level event or microtask. This means that if it throws, the error will be reported as uncaught as soon as possible. This is one reason to add the event as the last thing in the original event handler - any action done after adding the event will delay the report of errors in the event listener callbacks.

If an event is added in a setting that isn't known to be another event, it may cause the stream's listener to get that event before the listener is ready to handle it. We promise that after calling Stream.listen, you won't get any events until the code doing the listen has completed. Calling add in response to a function call of unknown origin may break that promise.

An onListen callback from the controller is not an asynchronous event, and adding events to the controller in the `onListen` callback is always wrong. The events will be delivered before the listener has even received the subscription yet.

The synchronous broadcast stream controller also has a restrictions that a normal stream controller does not: The add, addError, close and addStream methods must not be called while an event is being delivered. That is, if a callback on a subscription on the controller's stream causes a call to any of the functions above, the call will fail. A broadcast stream may have more than one listener, and if an event is added synchronously while another is being also in the process of being added, the latter event might reach some listeners before the former. To prevent that, an event cannot be added while a previous event is being fired. This guarantees that an event is fully delivered when the first add, addError or close returns, and further events will be delivered in the correct order.

This still only guarantees that the event is delivered to the subscription. If the subscription is paused, the actual callback may still happen later, and the event will instead be buffered by the subscription. Barring pausing, and the following buffered events that haven't been delivered yet, callbacks will be called synchronously when an event is added.

Adding an event to a synchronous non-broadcast stream controller while another event is in progress may cause the second event to be delayed and not be delivered synchronously, and until that event is delivered, the controller will not act synchronously.

Implements
  - StreamController<T>

## Constructors

SynchronousStreamController()

## Properties

done → Future
  Return a future which is completed when the StreamSink is finished. [...]
  read-only, inherited
hashCode → int
  The hash code for this object. [...]
  read-only, inherited
hasListener → bool
  Whether there is a subscriber on the Stream.
  read-only, inherited
isClosed → bool
  Whether the stream controller is closed for adding more events. [...]
  read-only, inherited
isPaused → bool
  Whether the subscription would need to buffer events. [...]
  read-only, inherited
onCancel ↔ ControllerCancelCallback
  The callback which is called when the stream is canceled. [...]
  read / write, inherited
onListen ↔ ControllerCallback
  The callback which is called when the stream is listened to. [...]
  read / write, inherited
onPause ↔ ControllerCallback
  The callback which is called when the stream is paused. [...]
  read / write, inherited
onResume ↔ ControllerCallback
  The callback which is called when the stream is resumed. [...]
  read / write, inherited
runtimeType → Type
  A representation of the runtime type of the object.
  read-only, inherited
sink → StreamSink<T>
  Returns a view of this object that only exposes the StreamSink interface.
  read-only, inherited
stream → Stream<T>
  The stream that this controller is controlling.
  read-only, inherited

## Methods

add(T data) → void
  Adds event to the controller's stream. [...]
addError(Object error, [ StackTrace stackTrace ]) → void
  Adds error to the controller's stream. [...]
close() → Future
  Closes the controller's stream. [...]
addStream(Stream<T> source, { bool cancelOnError }) → Future
  Receives events from `source` and puts them into this controller's stream. [...]
  inherited
noSuchMethod(Invocation invocation) → dynamic
  Invoked when a non-existent method or property is accessed. [...]
  inherited
toString() → String
  Returns a string representation of this object.
  inherited

## Operators

operator ==(dynamic other) → bool
  The equality operator. [...]
  inherited