|
21 | 21 | import io.reactivex.functions.Function;
|
22 | 22 | import io.reactivex.internal.disposables.DisposableHelper;
|
23 | 23 | import io.reactivex.internal.functions.ObjectHelper;
|
24 |
| -import io.reactivex.internal.queue.*; |
| 24 | +import io.reactivex.internal.fuseable.*; |
| 25 | +import io.reactivex.internal.queue.SpscLinkedArrayQueue; |
25 | 26 | import io.reactivex.internal.util.AtomicThrowable;
|
26 | 27 | import io.reactivex.plugins.RxJavaPlugins;
|
27 | 28 |
|
@@ -181,6 +182,8 @@ void drain() {
|
181 | 182 | }
|
182 | 183 |
|
183 | 184 | final Observer<? super R> a = actual;
|
| 185 | + final AtomicReference<SwitchMapInnerObserver<T, R>> active = this.active; |
| 186 | + final boolean delayErrors = this.delayErrors; |
184 | 187 |
|
185 | 188 | int missing = 1;
|
186 | 189 |
|
@@ -218,66 +221,85 @@ void drain() {
|
218 | 221 | SwitchMapInnerObserver<T, R> inner = active.get();
|
219 | 222 |
|
220 | 223 | if (inner != null) {
|
221 |
| - SpscLinkedArrayQueue<R> q = inner.queue; |
222 |
| - |
223 |
| - if (inner.done) { |
224 |
| - boolean empty = q.isEmpty(); |
225 |
| - if (delayErrors) { |
226 |
| - if (empty) { |
227 |
| - active.compareAndSet(inner, null); |
228 |
| - continue; |
| 224 | + SimpleQueue<R> q = inner.queue; |
| 225 | + |
| 226 | + if (q != null) { |
| 227 | + if (inner.done) { |
| 228 | + boolean empty = q.isEmpty(); |
| 229 | + if (delayErrors) { |
| 230 | + if (empty) { |
| 231 | + active.compareAndSet(inner, null); |
| 232 | + continue; |
| 233 | + } |
| 234 | + } else { |
| 235 | + Throwable ex = errors.get(); |
| 236 | + if (ex != null) { |
| 237 | + a.onError(errors.terminate()); |
| 238 | + return; |
| 239 | + } |
| 240 | + if (empty) { |
| 241 | + active.compareAndSet(inner, null); |
| 242 | + continue; |
| 243 | + } |
229 | 244 | }
|
230 |
| - } else { |
231 |
| - Throwable ex = errors.get(); |
232 |
| - if (ex != null) { |
233 |
| - a.onError(errors.terminate()); |
| 245 | + } |
| 246 | + |
| 247 | + boolean retry = false; |
| 248 | + |
| 249 | + for (;;) { |
| 250 | + if (cancelled) { |
234 | 251 | return;
|
235 | 252 | }
|
236 |
| - if (empty) { |
237 |
| - active.compareAndSet(inner, null); |
238 |
| - continue; |
| 253 | + if (inner != active.get()) { |
| 254 | + retry = true; |
| 255 | + break; |
239 | 256 | }
|
240 |
| - } |
241 |
| - } |
242 | 257 |
|
243 |
| - boolean retry = false; |
| 258 | + if (!delayErrors) { |
| 259 | + Throwable ex = errors.get(); |
| 260 | + if (ex != null) { |
| 261 | + a.onError(errors.terminate()); |
| 262 | + return; |
| 263 | + } |
| 264 | + } |
244 | 265 |
|
245 |
| - for (;;) { |
246 |
| - if (cancelled) { |
247 |
| - return; |
248 |
| - } |
249 |
| - if (inner != active.get()) { |
250 |
| - retry = true; |
251 |
| - break; |
252 |
| - } |
| 266 | + boolean d = inner.done; |
| 267 | + R v; |
253 | 268 |
|
254 |
| - if (!delayErrors) { |
255 |
| - Throwable ex = errors.get(); |
256 |
| - if (ex != null) { |
257 |
| - a.onError(errors.terminate()); |
258 |
| - return; |
| 269 | + try { |
| 270 | + v = q.poll(); |
| 271 | + } catch (Throwable ex) { |
| 272 | + Exceptions.throwIfFatal(ex); |
| 273 | + errors.addThrowable(ex); |
| 274 | + active.compareAndSet(inner, null); |
| 275 | + if (!delayErrors) { |
| 276 | + disposeInner(); |
| 277 | + s.dispose(); |
| 278 | + done = true; |
| 279 | + } else { |
| 280 | + inner.cancel(); |
| 281 | + } |
| 282 | + v = null; |
| 283 | + retry = true; |
259 | 284 | }
|
260 |
| - } |
| 285 | + boolean empty = v == null; |
261 | 286 |
|
262 |
| - boolean d = inner.done; |
263 |
| - R v = q.poll(); |
264 |
| - boolean empty = v == null; |
| 287 | + if (d && empty) { |
| 288 | + active.compareAndSet(inner, null); |
| 289 | + retry = true; |
| 290 | + break; |
| 291 | + } |
265 | 292 |
|
266 |
| - if (d && empty) { |
267 |
| - active.compareAndSet(inner, null); |
268 |
| - retry = true; |
269 |
| - break; |
270 |
| - } |
| 293 | + if (empty) { |
| 294 | + break; |
| 295 | + } |
271 | 296 |
|
272 |
| - if (empty) { |
273 |
| - break; |
| 297 | + a.onNext(v); |
274 | 298 | }
|
275 | 299 |
|
276 |
| - a.onNext(v); |
277 |
| - } |
278 |
| - |
279 |
| - if (retry) { |
280 |
| - continue; |
| 300 | + if (retry) { |
| 301 | + continue; |
| 302 | + } |
281 | 303 | }
|
282 | 304 | }
|
283 | 305 |
|
@@ -306,25 +328,49 @@ static final class SwitchMapInnerObserver<T, R> extends AtomicReference<Disposab
|
306 | 328 | private static final long serialVersionUID = 3837284832786408377L;
|
307 | 329 | final SwitchMapObserver<T, R> parent;
|
308 | 330 | final long index;
|
309 |
| - final SpscLinkedArrayQueue<R> queue; |
| 331 | + |
| 332 | + final int bufferSize; |
| 333 | + |
| 334 | + volatile SimpleQueue<R> queue; |
310 | 335 |
|
311 | 336 | volatile boolean done;
|
312 | 337 |
|
313 | 338 | SwitchMapInnerObserver(SwitchMapObserver<T, R> parent, long index, int bufferSize) {
|
314 | 339 | this.parent = parent;
|
315 | 340 | this.index = index;
|
316 |
| - this.queue = new SpscLinkedArrayQueue<R>(bufferSize); |
| 341 | + this.bufferSize = bufferSize; |
317 | 342 | }
|
318 | 343 |
|
319 | 344 | @Override
|
320 | 345 | public void onSubscribe(Disposable s) {
|
321 |
| - DisposableHelper.setOnce(this, s); |
| 346 | + if (DisposableHelper.setOnce(this, s)) { |
| 347 | + if (s instanceof QueueDisposable) { |
| 348 | + @SuppressWarnings("unchecked") |
| 349 | + QueueDisposable<R> qd = (QueueDisposable<R>) s; |
| 350 | + |
| 351 | + int m = qd.requestFusion(QueueDisposable.ANY); |
| 352 | + if (m == QueueDisposable.SYNC) { |
| 353 | + queue = qd; |
| 354 | + done = true; |
| 355 | + parent.drain(); |
| 356 | + return; |
| 357 | + } |
| 358 | + if (m == QueueDisposable.ASYNC) { |
| 359 | + queue = qd; |
| 360 | + return; |
| 361 | + } |
| 362 | + } |
| 363 | + |
| 364 | + queue = new SpscLinkedArrayQueue<R>(bufferSize); |
| 365 | + } |
322 | 366 | }
|
323 | 367 |
|
324 | 368 | @Override
|
325 | 369 | public void onNext(R t) {
|
326 | 370 | if (index == parent.unique) {
|
327 |
| - queue.offer(t); |
| 371 | + if (t != null) { |
| 372 | + queue.offer(t); |
| 373 | + } |
328 | 374 | parent.drain();
|
329 | 375 | }
|
330 | 376 | }
|
|
0 commit comments