@@ -56,7 +56,7 @@ public final class Signal<Value, Error: Swift.Error> {
5656 /// - generator: A closure that accepts an implicitly created observer
5757 /// that will act as an event emitter for the signal.
5858 public init ( _ generator: ( Observer ) -> Disposable ? ) {
59- state = . alive( SignalStateSnapshot ( ) )
59+ state = . alive( AliveState ( ) )
6060 updateLock = NSLock ( )
6161 updateLock. name = " org.reactivecocoa.ReactiveSwift.Signal.updateLock "
6262 sendLock = NSLock ( )
@@ -73,8 +73,7 @@ public final class Signal<Value, Error: Swift.Error> {
7373 //
7474 // Read directly.
7575 //
76- // - Extract the snapshot of a signal that is alive, and deliver events
77- // using the snapshot.
76+ // - Deliver `value` events in the `alive` state.
7877 //
7978 // `sendLock` must be acquired.
8079 //
@@ -83,12 +82,12 @@ public final class Signal<Value, Error: Swift.Error> {
8382 //
8483 // `updateLock` must be acquired.
8584 //
86- // - Transit from `alive` to `terminating`.
85+ // - Transition from `alive` to `terminating`.
8786 //
8887 // `updateLock` must be acquired.
8988 //
90- // - Extract the snapshot of a terminating signal to deliver the
91- // termination event, and transit from `terminating` to `terminated`.
89+ // - Deliver the termination event in the ` terminating` state, and
90+ // transition from `terminating` to `terminated`.
9291 //
9392 // Both `sendLock` and `updateLock` must be acquired. The state must
9493 // also be checked again after the locks are acquired. Fail gracefully
@@ -123,19 +122,18 @@ public final class Signal<Value, Error: Swift.Error> {
123122 // occasionally one of the senders waiting on `sendLock`.
124123 signal. updateLock. lock ( )
125124
126- if case let . alive( snapshot) = signal. state {
127- let newSnapshot = SignalStateSnapshot ( observers: snapshot. observers,
128- retaining: snapshot. retaining,
129- associated: event)
125+ if case let . alive( state) = signal. state {
126+ let newSnapshot = TerminatingState ( observers: state. observers,
127+ event: event)
130128 signal. state = . terminating( newSnapshot)
131129 signal. updateLock. unlock ( )
132130
133131 if signal. sendLock. try ( ) {
134- // Check whether the termination event has been handled by a
132+ // Check whether the terminating state has been handled by a
135133 // concurrent sender. If not, handle it.
136- if let snapshot = signal. shouldReallyTerminate ( ) {
137- for observer in snapshot . observers {
138- observer. action ( snapshot . associated )
134+ if let terminatingState = signal. shouldReallyTerminate ( ) {
135+ for observer in terminatingState . observers {
136+ observer. action ( terminatingState . event )
139137 }
140138 }
141139
@@ -169,16 +167,16 @@ public final class Signal<Value, Error: Swift.Error> {
169167 signal. sendLock. lock ( )
170168 // Start of the main protected section.
171169
172- if case let . alive( snapshot ) = signal. state {
173- for observer in snapshot . observers {
170+ if case let . alive( state ) = signal. state {
171+ for observer in state . observers {
174172 observer. action ( event)
175173 }
176174
177175 // Check if the status has been bumped to `terminating` due to a
178176 // concurrent or a recursive termination event.
179- if case . terminating = signal. state, let snapshot = signal. shouldReallyTerminate ( ) {
180- for observer in snapshot . observers {
181- observer. action ( snapshot . associated )
177+ if case . terminating = signal. state, let terminatingState = signal. shouldReallyTerminate ( ) {
178+ for observer in terminatingState . observers {
179+ observer. action ( terminatingState . event )
182180 }
183181
184182 shouldDispose = true
@@ -194,9 +192,9 @@ public final class Signal<Value, Error: Swift.Error> {
194192 if !shouldDispose, case . terminating = signal. state {
195193 signal. sendLock. lock ( )
196194
197- if let snapshot = signal. shouldReallyTerminate ( ) {
198- for observer in snapshot . observers {
199- observer. action ( snapshot . associated )
195+ if let terminatingState = signal. shouldReallyTerminate ( ) {
196+ for observer in terminatingState . observers {
197+ observer. action ( terminatingState . event )
200198 }
201199
202200 shouldDispose = true
@@ -311,7 +309,7 @@ public final class Signal<Value, Error: Swift.Error> {
311309 if case let . alive( snapshot) = state {
312310 var observers = snapshot. observers
313311 token = observers. insert ( observer)
314- state = . alive( SignalStateSnapshot ( observers: observers, retaining: self ) )
312+ state = . alive( AliveState ( observers: observers, retaining: self ) )
315313 }
316314 updateLock. unlock ( )
317315
@@ -322,8 +320,8 @@ public final class Signal<Value, Error: Swift.Error> {
322320 if case let . alive( snapshot) = s. state {
323321 var observers = snapshot. observers
324322 observers. remove ( using: token)
325- s. state = . alive( SignalStateSnapshot ( observers: observers,
326- retaining: observers. isEmpty ? nil : self ) )
323+ s. state = . alive( AliveState ( observers: observers,
324+ retaining: observers. isEmpty ? nil : self ) )
327325 }
328326 s. updateLock. unlock ( )
329327 }
@@ -343,58 +341,62 @@ public final class Signal<Value, Error: Swift.Error> {
343341/// The Swift compiler has also an optimization for enums with payloads that are
344342/// all reference counted, and at most one no-payload case.
345343private enum SignalState < Value, Error: Swift . Error > {
346- // FIXME: Change `()?` to `()` when concrete same-type requirement lands.
347344 /// The `Signal` is alive.
348- case alive( SignalStateSnapshot < Value , Error , ( ) ? > )
345+ case alive( AliveState < Value , Error > )
349346
350347 /// The `Signal` has received a termination event, and is about to be
351348 /// terminated.
352- case terminating( SignalStateSnapshot < Value , Error , Event < Value , Error > > )
349+ case terminating( TerminatingState < Value , Error > )
353350
354351 /// The `Signal` has terminated.
355352 case terminated
356353}
357354
358- /// The state snapshot of a `Signal` which contains the bag of observers ,
359- /// an optional self-retaining reference and an optional associated value.
360- ///
361- /// As the amount of state would definitely span over a cache line,
362- /// `SignalStateSnapshot` is set to be a reference type so that we can
363- /// atomically update the reference instead .
364- ///
365- /// - warning: In-place mutation should not be introduced to
366- /// `SignalStateSnapshot`. Copy the states and create a new instance .
367- private final class SignalStateSnapshot < Value, Error: Swift . Error , U > {
355+ // As the amount of state would definitely span over a cache line ,
356+ // `AliveState` and `TerminatingState` is set to be a reference type so
357+ // that we can atomically update the reference instead.
358+ //
359+ // Note that in-place mutation should not be introduced to `AliveState` and
360+ // `TerminatingState`. Copy the states and create a new instance .
361+
362+ /// The state of a `Signal` that is alive. It contains a bag of observers and
363+ /// an optional self-retaining reference .
364+ private final class AliveState < Value, Error: Swift . Error > {
368365 /// The observers of the `Signal`.
369366 fileprivate let observers : Bag < Signal < Value , Error > . Observer >
370367
371368 /// A self-retaining reference. It is set when there are one or more active
372369 /// observers.
373370 fileprivate let retaining : Signal < Value , Error > ?
374371
375- fileprivate let associated : U
376-
377- /// Create a snapshot.
372+ /// Create an alive state.
378373 ///
379374 /// - parameters:
380375 /// - observers: The latest bag of observers.
381376 /// - retaining: The self-retaining reference of the `Signal`, if necessary.
382- /// - associated: An associated value.
383- init ( observers: Bag < Signal < Value , Error > . Observer > = Bag ( ) , retaining: Signal < Value , Error > ? = nil , associated: U ) {
377+ init ( observers: Bag < Signal < Value , Error > . Observer > = Bag ( ) , retaining: Signal < Value , Error > ? = nil ) {
384378 self . observers = observers
385379 self . retaining = retaining
386- self . associated = associated
387380 }
388381}
389382
390- extension SignalStateSnapshot where U: ExpressibleByNilLiteral {
391- /// Create a snapshot.
383+ /// The state of a terminating `Signal`. It contains a bag of observers and the
384+ /// termination event.
385+ private final class TerminatingState < Value, Error: Swift . Error > {
386+ /// The observers of the `Signal`.
387+ fileprivate let observers : Bag < Signal < Value , Error > . Observer >
388+
389+ /// The termination event.
390+ fileprivate let event : Event < Value , Error >
391+
392+ /// Create a terminating state.
392393 ///
393394 /// - parameters:
394395 /// - observers: The latest bag of observers.
395- /// - retaining: The self-retaining reference of the `Signal`, if necessary.
396- convenience init ( observers: Bag < Signal < Value , Error > . Observer > = Bag ( ) , retaining: Signal < Value , Error > ? = nil ) {
397- self . init ( observers: observers, retaining: retaining, associated: nil )
396+ /// - event: The termination event.
397+ init ( observers: Bag < Signal < Value , Error > . Observer > , event: Event < Value , Error > ) {
398+ self . observers = observers
399+ self . event = event
398400 }
399401}
400402
0 commit comments