Hello @loom-dev When reading kotlin coroutine code:
https://github.com/Kotlin/kotlinx.coroutines/blob/8c27d51025d56a7b8de8eec2fb234b0094ce84f1/kotlinx-coroutines-core/common/src/Delay.kt#L9 https://github.com/Kotlin/kotlinx.coroutines/blob/8c27d51025d56a7b8de8eec2fb234b0094ce84f1/kotlinx-coroutines-core/common/src/Delay.kt#L149 I came up with a new idea — what if we provide an additional Delay interface? If the current scheduler implements this interface, we can use the scheduler’s own delay method. Otherwise, we fall back to `DelayedTaskSchedulers.schedule`. Currently, Loom only optimizes ForkJoinPool for this case. ``` java VirtualThreadScheduler scheduler(boolean revealBuiltin) { if (scheduler instanceof BuiltinDefaultScheduler builtin && !revealBuiltin) { return builtin.externalView(); } else { return scheduler; } } ``` But if I use Netty’s EventLoop as the scheduler, being able to implement delay based on the event loop would be fantastic. Best regards, Mengyang Li Alan Bateman <[email protected]> 于2025年10月9日周四 01:44写道: > > > On 08/10/2025 15:57, Mengyang Li wrote: > > > ``` > > Console output: > ``` bash > WARNING: Using custom default scheduler, this is an experimental feature! > class java.lang.Thread > VirtualThread[#27,VirtualThreadA]/runnable RUNNABLE currentThread > Thread[#3,main,5,main] current is virtual false > java.lang.RuntimeException > at > io.github.dreamlike.CustomerVirtualThreadScheduler.execute(CustomerVirtualThreadScheduler.java:16) > at > java.base/java.lang.VirtualThread.submitRunContinuation(VirtualThread.java:367) > at > java.base/java.lang.VirtualThread.externalSubmitRunContinuationOrThrow(VirtualThread.java:456) > at java.base/java.lang.VirtualThread.start(VirtualThread.java:734) > at java.base/java.lang.VirtualThread.start(VirtualThread.java:745) > at > java.base/java.lang.ThreadBuilders$VirtualThreadBuilder.start(ThreadBuilders.java:257) > at io.github.dreamlike.VTMain.main(VTMain.java:14) > ``` > > After checking the relevant code, it seems that execution goes through the > *first > branch* below. > > This behavior doesn’t appear to align with the semantics of a custom > scheduler — the nested virtual thread is submitted directly to > ct.getPool() instead of going through > CustomerVirtualThreadScheduler::execute. > > Thanks for the mail. You are correct. There is confusion between the > "custom default scheduler" and the "built-in default scheduler" when the > former delegates to the latter. I'll sort it out. > > -Alan >
