Skip to content

Commit 4685ed6

Browse files
committed
🚌 updated elimination backoff stack
1 parent 5087ae4 commit 4685ed6

File tree

2 files changed

+36
-12
lines changed

2 files changed

+36
-12
lines changed

EliminationArray.java

+6-4
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@
66

77
class EliminationArray<T> {
88
Exchanger<T>[] exchangers;
9+
final long TIMEOUT;
10+
final TimeUnit UNIT;
911
Random random;
10-
static final long TIMEOUT = 1;
11-
static final TimeUnit UNIT = TimeUnit.MILLISECONDS;
1212
// exchangers: array of exchangers
13-
// random: random number generator
1413
// TIMEOUT: exchange timeout number
1514
// UNIT: exchange timeout unit
15+
// random: random number generator
1616

1717
@SuppressWarnings("unchecked")
18-
public EliminationArray(int capacity) {
18+
public EliminationArray(int capacity, long timeout, TimeUnit unit) {
1919
exchangers = new Exchanger[capacity];
2020
for (int i=0; i<capacity; i++)
2121
exchangers[i] = new Exchanger<>();
2222
random = new Random();
23+
TIMEOUT = timeout;
24+
UNIT = unit;
2325
}
2426

2527
// 1. Try exchanging value on a random exchanger.

EliminationBackoffStack.java

+30-8
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,38 @@
22
import java.util.concurrent.*;
33
import java.util.concurrent.atomic.*;
44

5+
// Elimination-backoff stack is an unbounded lock-free LIFO linked list, that eliminates concurrent pairs of pushes and pops with exchanges.
56

67
class EliminationBackoffStack<T> {
78
AtomicReference<Node<T>> top;
89
EliminationArray<T> eliminationArray;
9-
static final int CAPACITY = 1;
10+
static final int CAPACITY = 100;
11+
static final long TIMEOUT = 10;
12+
static final TimeUnit UNIT = TimeUnit.MILLISECONDS;
1013
static ThreadLocal<RangePolicy> policy = new ThreadLocal<>() {
1114
protected RangePolicy initialValue() {
1215
return new RangePolicy(CAPACITY);
1316
}
1417
};
18+
// top: top of stack (null if empty)
19+
// eliminationArray: for exchanging values between push, pop
20+
// CAPACITY: capacity of elimination array
21+
// TIMEOUT: exchange timeout for elimination array
22+
// UNIT: exchange timeout unit for elimination array
23+
// policy: strategy for in use range of elimination array
1524

1625
public EliminationBackoffStack() {
1726
top = new AtomicReference<>(null);
18-
eliminationArray = new EliminationArray<>(CAPACITY);
27+
eliminationArray = new EliminationArray<>(CAPACITY, TIMEOUT, UNIT);
1928
}
2029

30+
// 1. Create a new node with given value.
31+
// 2. Try pushing it to stack.
32+
// 3a. If successful, return.
33+
// 3b. Otherwise, try exchanging on elimination array.
34+
// 4a. If exchange failed to find a pop, retry 2.
35+
// 4b. Otherwise, record success and return.
36+
// 4c. If timeout ocurred, record it.
2137
public void push(T x) {
2238
RangePolicy p = policy.get();
2339
Node<T> n = new Node<>(x);
@@ -32,17 +48,23 @@ public void push(T x) {
3248
}
3349
}
3450

51+
// 1. Try popping a node from stack.
52+
// 2a. If successful, return node's value
53+
// 2b. Otherwise, try exchanging on elimination array.
54+
// 3a. If exchange failed to find a push, retry 1.
55+
// 3b. Otherwise, return paired push value.
56+
// 3c. If timeout occurred, record it.
3557
public T pop() throws EmptyStackException {
3658
RangePolicy p = policy.get();
3759
while (true) {
38-
Node<T> n = tryPop();
39-
if (n != null) return n.value;
60+
Node<T> n = tryPop(); // 1
61+
if (n != null) return n.value; // 2a
4062
try {
41-
T y = eliminationArray.visit(null, p.range());
42-
if (y == null) continue;
43-
p.onSuccess(); return y;
63+
T y = eliminationArray.visit(null, p.range()); // 2b
64+
if (y == null) continue; // 3a
65+
p.onSuccess(); return y; // 3b
4466
}
45-
catch (TimeoutException e) { p.onTimeout(); }
67+
catch (TimeoutException e) { p.onTimeout(); } // 3c
4668
}
4769
}
4870

0 commit comments

Comments
 (0)