Skip to main content

Module serialized_multicast

Module serialized_multicast 

Source
Expand description

A multicast built on a SerializedDelivery that never terminates.

SerializedMulticast is what a subject is made of: it owns the observers, the termination, the ids that order the observers, and whatever else its host needs (R). Everything the host must read before it decides what to emit is therefore guarded by one lock — the delivery’s — so reading the termination, changing the host’s own state and queueing the events it produces is a single atomic step. A host that keeps state of its own next to this one loses that: every check-then-act pair across two locks is a window another thread, or a re-entrant callback, can slip through.

The multicast’s termination travels as an Action::Terminate, an ordinary value of the delivery. Nothing here may send an EventBatch::Termination to that delivery: that would drop the subscribers and the resources, silently killing the multicast. Keeping the delivery alive is what lets an observer that arrives after the termination still be notified with it, from the resources.

Recording the termination and queueing the action that delivers it is one step, and so is admitting a subscription — nothing can ever be queued behind the Action::Terminate, so the subscribers need no notion of termination of their own. The multicast is consequently terminated as soon as the termination is queued, not when it reaches the observers.

The observers live inside Subscribers, which the delivery loop owns while it delivers, so subscribing, unsubscribing and terminating all travel as Actions and touch the observers only outside the lock. Unsubscribing is the one that must take effect at once: the disposal writes a flag the subscribers check before every notification, and the queued Action::Prune only releases the observer afterwards.

§Replaying to a newcomer

A host that replays something to a joining observer — the current value, a buffer, the last value of a completed subject — hands it to Admission::Join under the lock, and the values travel inside the Action::Add. They are delivered by the delivery loop, right before the entry joins, and therefore in the same serialized stream as everything else: the snapshot the host took cannot miss a value forwarded after it, nor repeat one forwarded before it. The observer has moved into the entry by then, so this is also the only place it can be notified without racing the loop that may already be feeding the other observers.

The replay is consequently not guaranteed to happen before subscribe returns: it does when the delivery is idle, since the action is then applied on the subscribing thread, but a subscription made while a delivery is running is served by that delivery instead.

Structs§

MulticastDisposal
Unsubscribes one observer from a SerializedMulticast.
SerializedMulticast
A shared, serialized delivery of events to many observers, guarding the host’s state with it.

Enums§

Admission
What the host decided, under the lock, for an observer that wants to join.