Skip to content

Commit 5a58382

Browse files
committed
Lock-free BlockingIdentifierGenerator LoHi
1 parent 27c87c7 commit 5a58382

File tree

1 file changed

+43
-9
lines changed

1 file changed

+43
-9
lines changed

hibernate-reactive-core/src/main/java/org/hibernate/reactive/id/impl/BlockingIdentifierGenerator.java

+43-9
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import java.util.Objects;
1818
import java.util.concurrent.CompletableFuture;
1919
import java.util.concurrent.CompletionStage;
20+
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
2021

2122
import static org.hibernate.reactive.util.impl.CompletionStages.completedFuture;
2223

@@ -56,22 +57,55 @@ public abstract class BlockingIdentifierGenerator implements ReactiveIdentifierG
5657
//to reason about what the current state is and what the CombinerExecutor is
5758
//supposed to work on.
5859
private static class GeneratorState {
59-
private int loValue;
60-
private long hiValue;
60+
61+
private static final class LoHi {
62+
63+
private static final AtomicIntegerFieldUpdater<LoHi> LO_UPDATER = AtomicIntegerFieldUpdater.newUpdater(LoHi.class, "lo");
64+
private final long hi;
65+
private volatile long lo;
66+
67+
LoHi(long hi) {
68+
this.hi = hi;
69+
this.lo = 1;
70+
}
71+
72+
public long next(int blockSize) {
73+
if (lo >= blockSize) {
74+
return -1;
75+
}
76+
final long nextLo = LO_UPDATER.getAndIncrement(this);
77+
if (nextLo < blockSize) {
78+
return hi + nextLo;
79+
}
80+
return -1;
81+
}
82+
}
83+
84+
private volatile LoHi loHi;
85+
86+
public long hi(long hi) {
87+
loHi = new LoHi(hi);
88+
return hi;
89+
}
90+
91+
public long next(int blockSize) {
92+
final LoHi loHi = this.loHi;
93+
if (loHi == null) {
94+
return -1;
95+
}
96+
return loHi.next(blockSize);
97+
}
6198
}
6299

63100
//Critical section: needs to be accessed exclusively via the CombinerExecutor
64101
//when there's contention; direct invocation is allowed in the fast path.
65-
private synchronized long next() {
66-
return state.loValue > 0 && state.loValue < getBlockSize()
67-
? state.hiValue + state.loValue++
68-
: -1; //flag value indicating that we need to hit db
102+
private long next() {
103+
return state.next(getBlockSize());
69104
}
70105

71106
//Critical section: needs to be accessed exclusively via the CombinerExecutor
72-
private synchronized long next(long hi) {
73-
state.hiValue = hi;
74-
state.loValue = 1;
107+
private long next(long hi) {
108+
state.hi(hi);
75109
return hi;
76110
}
77111

0 commit comments

Comments
 (0)