Skip to content

Commit 98c49dc

Browse files
committed
Add blocking I/O test
1 parent ab8a6c0 commit 98c49dc

2 files changed

Lines changed: 80 additions & 284 deletions

File tree

core/src/main/java/io/netty/loom/NettyScheduler.java

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,19 @@ public class NettyScheduler implements Thread.VirtualThreadScheduler {
2727

2828
private final ConcurrentHashMap<Thread, SharedRef> unstartedThreads = new ConcurrentHashMap<>();
2929

30+
private final boolean perCarrierPollers;
31+
3032
public NettyScheduler(Thread.VirtualThreadScheduler jdkBuildinScheduler) {
3133
this.jdkBuildinScheduler = jdkBuildinScheduler;
3234
INSTANCE = this;
35+
perCarrierPollers = Integer.getInteger("jdk.pollerMode", -1) == 3;
3336
VarHandle.storeStoreFence();
3437
}
3538

39+
public boolean expectsPerCarrierPollers() {
40+
return perCarrierPollers;
41+
}
42+
3643
Thread.VirtualThreadScheduler jdkBuildinScheduler() {
3744
return jdkBuildinScheduler;
3845
}
@@ -47,23 +54,25 @@ public void onStart(Thread.VirtualThreadTask virtualThreadTask) {
4754
// or the vThreadFactory could provide in its build method something to access the VirtualThreadTask of an unstarted VirtualThread
4855
var assignedSchedulerRef = unstartedThreads.remove(virtualThreadTask.thread());
4956
if (assignedSchedulerRef == null) {
50-
// Read-Poller threads are special: if we run from a VThread managed by a VirtualThreadNettyScheduler,
51-
// we want should continue using that same scheduler for the Read-Poller thread.
52-
var currentThread = Thread.currentThread();
53-
if (currentThread.isVirtual()) {
54-
// TODO https://github.com/openjdk/loom/blob/12ddf39bb59252a8274d8b937bd075b2a6dbc3f8/src/java.base/share/classes/java/lang/VirtualThread.java#L270C18-L270C33
55-
// in theory should be easy to provide a VirtualThreadTask::current method to avoid the ScopedValue lookup
56-
var ctx = EventLoopScheduler.currentThreadSchedulerContext();
57-
var schedulerRef = ctx.scheduler();
58-
// See https://github.com/openjdk/loom/blob/12ddf39bb59252a8274d8b937bd075b2a6dbc3f8/src/java.base/share/classes/sun/nio/ch/Poller.java#L723C48-L723C59
59-
if (schedulerRef != null) {
60-
var runningScheduler = schedulerRef.get();
61-
if (runningScheduler != null && virtualThreadTask.thread().getName().endsWith("-Read-Poller")) {
62-
virtualThreadTask.attach(schedulerRef);
63-
if (runningScheduler.execute(virtualThreadTask)) {
64-
return;
57+
if (perCarrierPollers) {
58+
// Read-Poller threads are special: if we run from a VThread managed by a VirtualThreadNettyScheduler,
59+
// we want should continue using that same scheduler for the Read-Poller thread.
60+
var currentThread = Thread.currentThread();
61+
if (currentThread.isVirtual()) {
62+
// TODO https://github.com/openjdk/loom/blob/12ddf39bb59252a8274d8b937bd075b2a6dbc3f8/src/java.base/share/classes/java/lang/VirtualThread.java#L270C18-L270C33
63+
// in theory should be easy to provide a VirtualThreadTask::current method to avoid the ScopedValue lookup
64+
var ctx = EventLoopScheduler.currentThreadSchedulerContext();
65+
var schedulerRef = ctx.scheduler();
66+
// See https://github.com/openjdk/loom/blob/12ddf39bb59252a8274d8b937bd075b2a6dbc3f8/src/java.base/share/classes/sun/nio/ch/Poller.java#L723C48-L723C59
67+
if (schedulerRef != null) {
68+
var runningScheduler = schedulerRef.get();
69+
if (runningScheduler != null && virtualThreadTask.thread().getName().endsWith("-Read-Poller")) {
70+
virtualThreadTask.attach(schedulerRef);
71+
if (runningScheduler.execute(virtualThreadTask)) {
72+
return;
73+
}
74+
virtualThreadTask.attach(null);
6575
}
66-
virtualThreadTask.attach(null);
6776
}
6877
}
6978
}
@@ -103,6 +112,10 @@ static Thread assignUnstarted(Thread unstarted, SharedRef ref) {
103112
return unstarted;
104113
}
105114

115+
public static boolean perCarrierPollers() {
116+
return INSTANCE.perCarrierPollers;
117+
}
118+
106119
public static boolean isAvailable() {
107120
return INSTANCE != null;
108121
}

0 commit comments

Comments
 (0)