25
25
*/
26
26
public final class OnSubscribeRange implements OnSubscribe <Integer > {
27
27
28
- private final int start ;
29
- private final int end ;
28
+ private final int startIndex ;
29
+ private final int endIndex ;
30
30
31
- public OnSubscribeRange (int start , int end ) {
32
- this .start = start ;
33
- this .end = end ;
31
+ public OnSubscribeRange (int startIndex , int endIndex ) {
32
+ this .startIndex = startIndex ;
33
+ this .endIndex = endIndex ;
34
34
}
35
35
36
36
@ Override
37
- public void call (final Subscriber <? super Integer > o ) {
38
- o .setProducer (new RangeProducer (o , start , end ));
37
+ public void call (final Subscriber <? super Integer > childSubscriber ) {
38
+ childSubscriber .setProducer (new RangeProducer (childSubscriber , startIndex , endIndex ));
39
39
}
40
40
41
41
private static final class RangeProducer extends AtomicLong implements Producer {
42
42
/** */
43
43
private static final long serialVersionUID = 4114392207069098388L ;
44
44
45
- private final Subscriber <? super Integer > o ;
46
- private final int end ;
47
- private long index ;
45
+ private final Subscriber <? super Integer > childSubscriber ;
46
+ private final int endOfRange ;
47
+ private long currentIndex ;
48
48
49
- private RangeProducer (Subscriber <? super Integer > o , int start , int end ) {
50
- this .o = o ;
51
- this .index = start ;
52
- this .end = end ;
49
+ private RangeProducer (Subscriber <? super Integer > childSubscriber , int startIndex , int endIndex ) {
50
+ this .childSubscriber = childSubscriber ;
51
+ this .currentIndex = startIndex ;
52
+ this .endOfRange = endIndex ;
53
53
}
54
54
55
55
@ Override
56
- public void request (long n ) {
56
+ public void request (long requestedAmount ) {
57
57
if (get () == Long .MAX_VALUE ) {
58
58
// already started with fast-path
59
59
return ;
60
60
}
61
- if (n == Long .MAX_VALUE && compareAndSet (0L , Long .MAX_VALUE )) {
61
+ if (requestedAmount == Long .MAX_VALUE && compareAndSet (0L , Long .MAX_VALUE )) {
62
62
// fast-path without backpressure
63
63
fastpath ();
64
- } else if (n > 0L ) {
65
- long c = BackpressureUtils .getAndAddRequest (this , n );
64
+ } else if (requestedAmount > 0L ) {
65
+ long c = BackpressureUtils .getAndAddRequest (this , requestedAmount );
66
66
if (c == 0L ) {
67
67
// backpressure is requested
68
- slowpath (n );
68
+ slowpath (requestedAmount );
69
69
}
70
70
}
71
71
}
72
72
73
73
/**
74
74
*
75
75
*/
76
- void slowpath (long r ) {
77
- long idx = index ;
76
+ void slowpath (long requestedAmount ) {
77
+ long positionInRange = currentIndex ;
78
+ long emitted = 0L ;
78
79
while (true ) {
79
80
/*
80
81
* This complicated logic is done to avoid touching the volatile `index` and `requested` values
81
82
* during the loop itself. If they are touched during the loop the performance is impacted significantly.
82
83
*/
83
- long fs = end - idx + 1 ;
84
- long e = Math .min (fs , r );
85
- final boolean complete = fs <= r ;
84
+ long remainingAmountOrEndIndex = endOfRange - positionInRange + 1 ;
85
+ final boolean complete = remainingAmountOrEndIndex <= requestedAmount ;
86
86
87
- fs = e + idx ;
88
- final Subscriber <? super Integer > o = this .o ;
87
+ remainingAmountOrEndIndex = Math . min ( remainingAmountOrEndIndex , requestedAmount ) + positionInRange ;
88
+ final Subscriber <? super Integer > childSubscriber = this .childSubscriber ;
89
89
90
- for (long i = idx ; i != fs ; i ++) {
91
- if (o .isUnsubscribed ()) {
90
+ for (long runningIndex = positionInRange ; runningIndex != remainingAmountOrEndIndex ; runningIndex ++) {
91
+ if (childSubscriber .isUnsubscribed ()) {
92
92
return ;
93
93
}
94
- o .onNext ((int ) i );
94
+ childSubscriber .onNext ((int ) runningIndex );
95
95
}
96
96
97
97
if (complete ) {
98
- if (o .isUnsubscribed ()) {
98
+ if (childSubscriber .isUnsubscribed ()) {
99
99
return ;
100
100
}
101
- o .onCompleted ();
101
+ childSubscriber .onCompleted ();
102
102
return ;
103
103
}
104
104
105
- idx = fs ;
106
- index = fs ;
105
+ emitted -= remainingAmountOrEndIndex - positionInRange ;
107
106
108
- r = addAndGet (-e );
109
- if (r == 0L ) {
110
- // we're done emitting the number requested so return
111
- return ;
107
+ positionInRange = remainingAmountOrEndIndex ;
108
+
109
+ requestedAmount = get () + emitted ;
110
+ if (requestedAmount == 0L ) {
111
+ currentIndex = remainingAmountOrEndIndex ;
112
+ requestedAmount = addAndGet (emitted );
113
+ if (requestedAmount == 0L ) {
114
+ // we're done emitting the number requested so return
115
+ return ;
116
+ }
117
+ emitted = 0L ;
112
118
}
113
119
}
114
120
}
@@ -117,18 +123,18 @@ void slowpath(long r) {
117
123
*
118
124
*/
119
125
void fastpath () {
120
- final long end = this .end + 1L ;
121
- final Subscriber <? super Integer > o = this .o ;
122
- for (long i = index ; i != end ; i ++) {
123
- if (o .isUnsubscribed ()) {
126
+ final long end = this .endOfRange + 1L ;
127
+ final Subscriber <? super Integer > childSubscriber = this .childSubscriber ;
128
+ for (long runningIndex = currentIndex ; runningIndex != end ; runningIndex ++) {
129
+ if (childSubscriber .isUnsubscribed ()) {
124
130
return ;
125
131
}
126
- o .onNext ((int ) i );
132
+ childSubscriber .onNext ((int ) runningIndex );
127
133
}
128
- if (!o .isUnsubscribed ()) {
129
- o .onCompleted ();
134
+ if (!childSubscriber .isUnsubscribed ()) {
135
+ childSubscriber .onCompleted ();
130
136
}
131
137
}
132
138
}
133
139
134
- }
140
+ }
0 commit comments