@@ -91,7 +91,7 @@ public void onStart() {
91
91
// we decouple the Producer chain while keeping the Subscription chain together (perf benefit) via super(actual)
92
92
request (RxRingBuffer .SIZE );
93
93
}
94
-
94
+
95
95
/*
96
96
* This is expected to be executed sequentially as per the Rx contract or it will not work.
97
97
*/
@@ -309,12 +309,7 @@ public Boolean call(InnerSubscriber<T> s) {
309
309
if (s .q != null ) {
310
310
long r = mergeProducer .requested ;
311
311
int emitted = 0 ;
312
- if (r < 0 ) {
313
- emitted += drainAll (s );
314
- } else if (r > 0 ) {
315
- emitted += drainRequested (s , r );
316
- }
317
-
312
+ emitted += s .drainQueue ();
318
313
if (emitted > 0 ) {
319
314
/*
320
315
* `s.emitted` is not volatile (because of performance impact of making it so shown by JMH tests)
@@ -336,46 +331,6 @@ public Boolean call(InnerSubscriber<T> s) {
336
331
return Boolean .TRUE ;
337
332
}
338
333
339
- private int drainRequested (InnerSubscriber <T > s , long r ) {
340
- int emitted = 0 ;
341
- // drain what was requested
342
- long toEmit = r ;
343
- Object o ;
344
- for (int i = 0 ; i < toEmit ; i ++) {
345
- o = s .q .poll ();
346
- if (o == null ) {
347
- // no more items
348
- break ;
349
- } else if (s .q .isCompleted (o )) {
350
- completeInner (s );
351
- } else {
352
- if (!s .q .accept (o , actual )) {
353
- emitted ++;
354
- }
355
- }
356
- }
357
-
358
- // decrement the number we emitted from outstanding requests
359
- mergeProducer .REQUESTED .getAndAdd (mergeProducer , -emitted );
360
- return emitted ;
361
- }
362
-
363
- private int drainAll (InnerSubscriber <T > s ) {
364
- int emitted = 0 ;
365
- // drain it all
366
- Object o ;
367
- while ((o = s .q .poll ()) != null ) {
368
- if (s .q .isCompleted (o )) {
369
- completeInner (s );
370
- } else {
371
- if (!s .q .accept (o , actual )) {
372
- emitted ++;
373
- }
374
- }
375
- }
376
- return emitted ;
377
- }
378
-
379
334
};
380
335
381
336
@ Override
@@ -451,7 +406,6 @@ private static final class InnerSubscriber<T> extends Subscriber<T> {
451
406
@ SuppressWarnings ("rawtypes" )
452
407
static final AtomicIntegerFieldUpdater <InnerSubscriber > ONCE_UPDATER = AtomicIntegerFieldUpdater .newUpdater (InnerSubscriber .class , "once" );
453
408
private final RxRingBuffer q = RxRingBuffer .getSpmcInstance ();
454
- private boolean mayNeedToDrain = false ;
455
409
/* protected by emitLock */
456
410
int emitted = 0 ;
457
411
final int THRESHOLD = (int ) (q .capacity () * 0.7 );
@@ -526,12 +480,9 @@ private void emit(T t, boolean complete) {
526
480
if (parentSubscriber .getEmitLock ()) {
527
481
enqueue = false ;
528
482
try {
529
- // when we have the lock, nothing else can cause producer.requested to decrement, but it can increment at any time
530
- if (mayNeedToDrain ) {
531
- // drain the queue if there is anything in it before emitting the current value
532
- emitted += drainQueue ();
533
- mayNeedToDrain = false ;
534
- }
483
+ // drain the queue if there is anything in it before emitting the current value
484
+ emitted += drainQueue ();
485
+ // }
535
486
if (producer == null ) {
536
487
// no backpressure requested
537
488
if (complete ) {
@@ -600,7 +551,7 @@ private void emit(T t, boolean complete) {
600
551
* r.o.OperatorMergePerf.mergeNSyncStreamsOfN 1000 thrpt 5 78.795 1.766 ops/s
601
552
* } </pre>
602
553
*/
603
- mayNeedToDrain = ! parentSubscriber .drainQueuesIfNeeded ();
554
+ parentSubscriber .drainQueuesIfNeeded ();
604
555
}
605
556
}
606
557
@@ -611,41 +562,57 @@ private void enqueue(T t, boolean complete) {
611
562
} else {
612
563
q .onNext (t );
613
564
}
614
- mayNeedToDrain = true ;
615
565
} catch (MissingBackpressureException e ) {
616
566
onError (e );
617
567
}
618
568
}
619
569
620
- private int drainQueue () {
621
- int emittedWhileDraining = 0 ;
622
- if (q != null ) {
623
- if (producer == null ) {
624
- Object o ;
625
- while ((o = q .poll ()) != null ) {
626
- if (!q .accept (o , parentSubscriber .actual )) {
627
- // non-terminal event so let's increment count
628
- emittedWhileDraining ++;
629
- }
570
+ private int drainRequested () {
571
+ int emitted = 0 ;
572
+ // drain what was requested
573
+ long toEmit = producer .requested ;
574
+ Object o ;
575
+ for (int i = 0 ; i < toEmit ; i ++) {
576
+ o = q .poll ();
577
+ if (o == null ) {
578
+ // no more items
579
+ break ;
580
+ } else if (q .isCompleted (o )) {
581
+ parentSubscriber .completeInner (this );
582
+ } else {
583
+ if (!q .accept (o , parentSubscriber .actual )) {
584
+ emitted ++;
630
585
}
586
+ }
587
+ }
588
+
589
+ // decrement the number we emitted from outstanding requests
590
+ producer .REQUESTED .getAndAdd (producer , -emitted );
591
+ return emitted ;
592
+ }
593
+
594
+ private int drainAll () {
595
+ int emitted = 0 ;
596
+ // drain it all
597
+ Object o ;
598
+ while ((o = q .poll ()) != null ) {
599
+ if (q .isCompleted (o )) {
600
+ parentSubscriber .completeInner (this );
631
601
} else {
632
- long toEmit = producer .requested ;
633
- for (int i = 0 ; i < toEmit ; i ++) {
634
- Object o = q .poll ();
635
- if (o == null ) {
636
- break ;
637
- } else {
638
- if (!q .accept (o , parentSubscriber .actual )) {
639
- // non-terminal event so let's increment count
640
- emittedWhileDraining ++;
641
- }
642
- }
602
+ if (!q .accept (o , parentSubscriber .actual )) {
603
+ emitted ++;
643
604
}
644
- // decrement the number we emitted from outstanding requests
645
- producer .REQUESTED .getAndAdd (producer , -emittedWhileDraining );
646
605
}
647
606
}
648
- return emittedWhileDraining ;
607
+ return emitted ;
608
+ }
609
+
610
+ private int drainQueue () {
611
+ if (producer != null ) {
612
+ return drainRequested ();
613
+ } else {
614
+ return drainAll ();
615
+ }
649
616
}
650
617
}
651
618
}
0 commit comments