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§
- Multicast
Disposal - Unsubscribes one observer from a
SerializedMulticast. - Serialized
Multicast - 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.