Skip to content

Commit ad2d5b8

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

File tree

1 file changed

+40
-9
lines changed

1 file changed

+40
-9
lines changed

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

+40-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,52 @@ 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+
final long nextLo = LO_UPDATER.getAndIncrement(this);
74+
if (nextLo < blockSize) {
75+
return hi + nextLo;
76+
}
77+
return -1;
78+
}
79+
}
80+
81+
private volatile LoHi loHi;
82+
83+
public long hi(long hi) {
84+
loHi = new LoHi(hi);
85+
return hi;
86+
}
87+
88+
public long next(int blockSize) {
89+
final LoHi loHi = this.loHi;
90+
if (loHi == null) {
91+
return -1;
92+
}
93+
return loHi.next(blockSize);
94+
}
6195
}
6296

6397
//Critical section: needs to be accessed exclusively via the CombinerExecutor
6498
//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
99+
private long next() {
100+
return state.next(getBlockSize());
69101
}
70102

71103
//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;
104+
private long next(long hi) {
105+
state.hi(hi);
75106
return hi;
76107
}
77108

0 commit comments

Comments
 (0)