1515 */
1616package rx .internal .operators ;
1717
18+ import java .util .concurrent .atomic .AtomicLong ;
19+
1820import rx .Observable .Operator ;
19- import rx .Subscriber ;
20- import rx .exceptions .OnErrorThrowable ;
21- import rx .functions .Func0 ;
22- import rx .functions .Func1 ;
21+ import rx .*;
22+ import rx .exceptions .*;
23+ import rx .functions .*;
2324
2425/**
2526 * Applies a function of your choosing to every item emitted by an {@code Observable}, and emits the results of
@@ -41,13 +42,18 @@ public OperatorMapNotification(Func1<? super T, ? extends R> onNext, Func1<? sup
4142
4243 @ Override
4344 public Subscriber <? super T > call (final Subscriber <? super R > o ) {
44- return new Subscriber <T >(o ) {
45-
45+ Subscriber <T > subscriber = new Subscriber <T >() {
46+ SingleEmitter <R > emitter ;
47+ @ Override
48+ public void setProducer (Producer producer ) {
49+ emitter = new SingleEmitter <R >(o , producer , this );
50+ o .setProducer (emitter );
51+ }
52+
4653 @ Override
4754 public void onCompleted () {
4855 try {
49- o .onNext (onCompleted .call ());
50- o .onCompleted ();
56+ emitter .offerAndComplete (onCompleted .call ());
5157 } catch (Throwable e ) {
5258 o .onError (e );
5359 }
@@ -56,8 +62,7 @@ public void onCompleted() {
5662 @ Override
5763 public void onError (Throwable e ) {
5864 try {
59- o .onNext (onError .call (e ));
60- o .onCompleted ();
65+ emitter .offerAndComplete (onError .call (e ));
6166 } catch (Throwable e2 ) {
6267 o .onError (e );
6368 }
@@ -66,13 +71,154 @@ public void onError(Throwable e) {
6671 @ Override
6772 public void onNext (T t ) {
6873 try {
69- o . onNext (onNext .call (t ));
74+ emitter . offer (onNext .call (t ));
7075 } catch (Throwable e ) {
7176 o .onError (OnErrorThrowable .addValueAsLastCause (e , t ));
7277 }
7378 }
7479
7580 };
81+ o .add (subscriber );
82+ return subscriber ;
7683 }
77-
78- }
84+ static final class SingleEmitter <T > extends AtomicLong implements Producer , Subscription {
85+ /** */
86+ private static final long serialVersionUID = -249869671366010660L ;
87+ final NotificationLite <T > nl ;
88+ final Subscriber <? super T > child ;
89+ final Producer producer ;
90+ final Subscription cancel ;
91+ volatile Object value ;
92+ volatile boolean complete ;
93+ /** Guarded by this. */
94+ boolean emitting ;
95+ /** Guarded by this. */
96+ boolean missed ;
97+
98+ public SingleEmitter (Subscriber <? super T > child , Producer producer , Subscription cancel ) {
99+ this .child = child ;
100+ this .producer = producer ;
101+ this .cancel = cancel ;
102+ this .nl = NotificationLite .instance ();
103+ }
104+ @ Override
105+ public void request (long n ) {
106+ for (;;) {
107+ long r = get ();
108+ if (r < 0 ) {
109+ return ;
110+ }
111+ long u = r + n ;
112+ if (u < 0 ) {
113+ u = Long .MAX_VALUE ;
114+ }
115+ if (compareAndSet (r , u )) {
116+ producer .request (n );
117+ drain ();
118+ return ;
119+ }
120+ }
121+ }
122+
123+ void produced (long n ) {
124+ for (;;) {
125+ long r = get ();
126+ if (r < 0 ) {
127+ return ;
128+ }
129+ long u = r - n ;
130+ if (u < 0 ) {
131+ throw new IllegalStateException ("More produced (" + n + ") than requested (" + r + ")" );
132+ }
133+ if (compareAndSet (r , u )) {
134+ return ;
135+ }
136+ }
137+ }
138+
139+ public void offer (T value ) {
140+ if (this .value != null ) {
141+ child .onError (new MissingBackpressureException ());
142+ unsubscribe ();
143+ } else {
144+ this .value = nl .next (value );
145+ drain ();
146+ }
147+ }
148+ public void offerAndComplete (T value ) {
149+ if (this .value != null ) {
150+ child .onError (new MissingBackpressureException ());
151+ unsubscribe ();
152+ } else {
153+ this .value = nl .next (value );
154+ this .complete = true ;
155+ drain ();
156+ }
157+ }
158+
159+ void drain () {
160+ synchronized (this ) {
161+ if (emitting ) {
162+ missed = true ;
163+ return ;
164+ }
165+ emitting = true ;
166+ missed = false ;
167+ }
168+ boolean skipFinal = false ;
169+ try {
170+ for (;;) {
171+
172+ long r = get ();
173+ boolean c = complete ;
174+ Object v = value ;
175+
176+ if (c && v == null ) {
177+ child .onCompleted ();
178+ } else
179+ if (r > 0 && v != null ) {
180+ value = null ;
181+ child .onNext (nl .getValue (v ));
182+ if (c ) {
183+ child .onCompleted ();
184+ skipFinal = true ;
185+ return ;
186+ } else {
187+ produced (1 );
188+ }
189+ }
190+
191+ synchronized (this ) {
192+ if (!missed ) {
193+ skipFinal = true ;
194+ emitting = false ;
195+ return ;
196+ }
197+ missed = false ;
198+ }
199+ }
200+ } finally {
201+ if (!skipFinal ) {
202+ synchronized (this ) {
203+ emitting = false ;
204+ }
205+ }
206+ }
207+ }
208+
209+ @ Override
210+ public boolean isUnsubscribed () {
211+ return get () < 0 ;
212+ }
213+ @ Override
214+ public void unsubscribe () {
215+ long r = get ();
216+ if (r != Long .MIN_VALUE ) {
217+ r = getAndSet (Long .MIN_VALUE );
218+ if (r != Long .MIN_VALUE ) {
219+ cancel .unsubscribe ();
220+ }
221+ }
222+ }
223+ }
224+ }
0 commit comments