@@ -42,34 +42,59 @@ extension Publishers {
4242 }
4343
4444 public func receive< S: Subscriber > ( subscriber: S ) where Failure == S . Failure , Output == S . Input {
45- upstream. subscribe (
46- WithLatestFromSink < Upstream , Other , S > (
47- downstream: subscriber,
48- otherSink: WithLatestFromOtherSink ( publisher: other) ,
49- transform: transform
50- )
51- )
45+ let otherSink = WithLatestFromOtherSink ( publisher: other)
46+ let upstreamSink = WithLatestFromSink ( upstream: upstream, downstream: subscriber, otherSink: otherSink, transform: transform)
47+ subscriber. receive ( subscription: WithLatestFromSubscription ( sink: upstreamSink) )
5248 }
5349 }
5450
51+ // MARK: - Subscription
52+
53+ fileprivate class WithLatestFromSubscription < Upstream: Publisher , Other: Publisher , Downstream: Subscriber > : Subscription
54+ where Upstream. Failure == Other . Failure , Upstream. Failure == Downstream . Failure
55+ {
56+
57+ var sink : WithLatestFromSink < Upstream , Other , Downstream > ?
58+
59+ init ( sink: WithLatestFromSink < Upstream , Other , Downstream > ) {
60+ self . sink = sink
61+ }
62+
63+ func request( _ demand: Subscribers . Demand ) {
64+ sink? . signalDemand ( demand)
65+ }
66+
67+ func cancel( ) {
68+ self . sink? . terminateSubscription ( )
69+ self . sink = nil
70+ }
71+ }
72+
73+ // MARK: - Main Sink
74+
5575 fileprivate class WithLatestFromSink < Upstream: Publisher , Other: Publisher , Downstream: Subscriber > : Subscriber
56- where Upstream. Failure == Other . Failure , Upstream. Failure == Downstream . Failure {
76+ where Upstream. Failure == Other . Failure , Upstream. Failure == Downstream . Failure
77+ {
5778
5879 typealias Input = Upstream . Output
5980 typealias Failure = Upstream . Failure
6081
61- let downstream : Downstream
82+ var queue : SinkQueue < Downstream >
83+ var upstreamSubscription : Subscription ?
84+
6285 let otherSink : WithLatestFromOtherSink < Other >
6386 let transform : ( Upstream . Output , Other . Output ) -> Downstream . Input
6487
65- init ( downstream: Downstream , otherSink: WithLatestFromOtherSink < Other > , transform: @escaping ( Input , Other . Output ) -> Downstream . Input ) {
66- self . downstream = downstream
88+ init ( upstream : Upstream , downstream: Downstream , otherSink: WithLatestFromOtherSink < Other > , transform: @escaping ( Input , Other . Output ) -> Downstream . Input ) {
89+ self . queue = SinkQueue ( sink : downstream)
6790 self . otherSink = otherSink
6891 self . transform = transform
92+
93+ upstream. subscribe ( self )
6994 }
7095
7196 func receive( subscription: Subscription ) {
72- downstream . receive ( subscription : subscription)
97+ self . upstreamSubscription = subscription
7398 otherSink. subscribe ( )
7499 }
75100
@@ -83,15 +108,27 @@ extension Publishers {
83108 // the dropped item by returning a Subscribers.Demand of 1.
84109 return . max( 1 )
85110 }
86- return downstream . receive ( transform ( input, otherInput) )
111+ return queue . enqueue ( transform ( input, otherInput) )
87112 }
88113
89114 func receive( completion: Subscribers . Completion < Downstream . Failure > ) {
115+ _ = queue. enqueue ( completion: completion)
116+ }
117+
118+ func signalDemand( _ demand: Subscribers . Demand ) {
119+ let spareDemand = queue. requestDemand ( demand)
120+ guard spareDemand > . none else { return }
121+ upstreamSubscription? . request ( spareDemand)
122+ }
123+
124+ func terminateSubscription( ) {
90125 otherSink. terminateSubscription ( )
91- downstream . receive ( completion : completion )
126+ upstreamSubscription ? . cancel ( )
92127 }
93128 }
94129
130+ // MARK: - Other Sink
131+
95132 fileprivate class WithLatestFromOtherSink < P: Publisher > : Subscriber {
96133
97134 typealias Input = P . Output
@@ -101,7 +138,6 @@ extension Publishers {
101138 private ( set) var lastInput : Input ?
102139 private var subscription : Subscription ?
103140
104-
105141 init ( publisher: P ) {
106142 self . publisher = publisher. eraseToAnyPublisher ( )
107143 }
@@ -120,9 +156,7 @@ extension Publishers {
120156 return . none
121157 }
122158
123- func receive( completion: Subscribers . Completion < Failure > ) {
124- subscription = nil
125- }
159+ func receive( completion: Subscribers . Completion < Failure > ) { }
126160
127161 func terminateSubscription( ) {
128162 subscription? . cancel ( )
0 commit comments