Skip to content

Commit 7a77072

Browse files
committed
Merge pull request #3177 from akarnokd/BackpressureUtilsExtra
BackpressureUtils capped add/multiply methods + tests
2 parents d71314e + 1cad3e6 commit 7a77072

File tree

2 files changed

+72
-10
lines changed

2 files changed

+72
-10
lines changed

src/main/java/rx/internal/operators/BackpressureUtils.java

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,7 @@ public static <T> long getAndAddRequest(AtomicLongFieldUpdater<T> requested, T o
4444
// add n to field but check for overflow
4545
while (true) {
4646
long current = requested.get(object);
47-
long next = current + n;
48-
// check for overflow
49-
if (next < 0) {
50-
next = Long.MAX_VALUE;
51-
}
47+
long next = addCap(current, n);
5248
if (requested.compareAndSet(object, current, next)) {
5349
return current;
5450
}
@@ -70,14 +66,41 @@ public static long getAndAddRequest(AtomicLong requested, long n) {
7066
// add n to field but check for overflow
7167
while (true) {
7268
long current = requested.get();
73-
long next = current + n;
74-
// check for overflow
75-
if (next < 0) {
76-
next = Long.MAX_VALUE;
77-
}
69+
long next = addCap(current, n);
7870
if (requested.compareAndSet(current, next)) {
7971
return current;
8072
}
8173
}
8274
}
75+
76+
/**
77+
* Multiplies two positive longs and caps the result at Long.MAX_VALUE.
78+
* @param a the first value
79+
* @param b the second value
80+
* @return the capped product of a and b
81+
*/
82+
public static long multiplyCap(long a, long b) {
83+
long u = a * b;
84+
if (((a | b) >>> 31) != 0) {
85+
if (b != 0L && (u / b != a)) {
86+
u = Long.MAX_VALUE;
87+
}
88+
}
89+
return u;
90+
}
91+
92+
/**
93+
* Adds two positive longs and caps the result at Long.MAX_VALUE.
94+
* @param a the first value
95+
* @param b the second value
96+
* @return the capped sum of a and b
97+
*/
98+
public static long addCap(long a, long b) {
99+
long u = a + b;
100+
if (u < 0L) {
101+
u = Long.MAX_VALUE;
102+
}
103+
return u;
104+
}
105+
83106
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Copyright 2015 Netflix, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package rx.internal.operators;
17+
18+
import org.junit.Test;
19+
import static org.junit.Assert.*;
20+
21+
public class BackpressureUtilsTest {
22+
@Test
23+
public void testAddCap() {
24+
assertEquals(2L, BackpressureUtils.addCap(1, 1));
25+
assertEquals(Long.MAX_VALUE, BackpressureUtils.addCap(1, Long.MAX_VALUE - 1));
26+
assertEquals(Long.MAX_VALUE, BackpressureUtils.addCap(1, Long.MAX_VALUE));
27+
assertEquals(Long.MAX_VALUE, BackpressureUtils.addCap(Long.MAX_VALUE - 1, Long.MAX_VALUE - 1));
28+
assertEquals(Long.MAX_VALUE, BackpressureUtils.addCap(Long.MAX_VALUE, Long.MAX_VALUE));
29+
}
30+
31+
@Test
32+
public void testMultiplyCap() {
33+
assertEquals(6, BackpressureUtils.multiplyCap(2, 3));
34+
assertEquals(Long.MAX_VALUE, BackpressureUtils.multiplyCap(2, Long.MAX_VALUE));
35+
assertEquals(Long.MAX_VALUE, BackpressureUtils.multiplyCap(Long.MAX_VALUE, Long.MAX_VALUE));
36+
assertEquals(Long.MAX_VALUE, BackpressureUtils.multiplyCap(1L << 32, 1L << 32));
37+
38+
}
39+
}

0 commit comments

Comments
 (0)