Fix overflow bug in MultithreadEventExecutorGroup (#10474)
Motivation: We should pluck executors in round-robin, but at the 32-bit overflow boundary, the round-robin sequence was disrupted when the number of executors are not a power of 2. Modifications: Changed the index counter from a 32-bit to a 64-bit long. The overflow bug is still technically there, but it now takes so long to reach that it will never happen in practice. For example, 2^63 nanoseconds is almost 300 years. Result: The round-robin behaviour is now preserved in practice. This is a backport of https://github.com/netty/netty/pull/10468
This commit is contained in:
parent
02676e369c
commit
41313130a3
@ -25,6 +25,7 @@ import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
/**
|
||||
* {@link EventExecutorGroup} implementation that handles their tasks with multiple threads at
|
||||
@ -166,7 +167,10 @@ public class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {
|
||||
readonlyChildren = Collections.unmodifiableList(Arrays.asList(children));
|
||||
}
|
||||
|
||||
private final AtomicInteger idx = new AtomicInteger();
|
||||
// Use a 'long' counter to avoid non-round-robin behaviour at the 32-bit overflow boundary.
|
||||
// The 64-bit long solves this by placing the overflow so far into the future, that no system
|
||||
// will encounter this in practice.
|
||||
private final AtomicLong idx = new AtomicLong();
|
||||
|
||||
/**
|
||||
* The {@link EventExecutor}s that are used by this {@link MultithreadEventExecutorGroup}.
|
||||
@ -182,9 +186,9 @@ public class MultithreadEventExecutorGroup extends AbstractEventExecutorGroup {
|
||||
@Override
|
||||
public EventExecutor next() {
|
||||
if (powerOfTwo) {
|
||||
return children[idx.getAndIncrement() & children.length - 1];
|
||||
return children[(int) idx.getAndIncrement() & children.length - 1];
|
||||
}
|
||||
return children[Math.abs(idx.getAndIncrement() % children.length)];
|
||||
return children[(int) Math.abs(idx.getAndIncrement() % children.length)];
|
||||
}
|
||||
|
||||
private static boolean isPowerOfTwo(int val) {
|
||||
|
Loading…
Reference in New Issue
Block a user